claude-harness/docs/superpowers/plans/2026-10-24-dsh-sdd.md
Andrey Epifancev c8b92fae01 docs(dsh): пробный прогон SDD — режимы, дефект и fix-loop (#41)
Три задачи в 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>
2026-10-24 17:49:38 +04:00

23 KiB
Raw Blame History

DSH-native SDD — 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: Дать DSH-сессии инструкцию исполнения плана субагентами (асинхронный subagent, ledger, ревью, fix-loop) и opt-in overlay профиля с глубиной 2 и двумя маршрутами моделей; доказать семантику пробным прогоном из 3 задач.

Architecture: Три слоя. (1) dsh/subagent-models.yml — overlay, который владелец копирует в cordis.patch.yml профиля: включает subagent-model-selection-settings (маршруты deepseek-flash / deepseek-v4-pro) и subagent.maxDepth: 2; в бандл не входит, иначе падает headless. (2) dsh/skills/sdd/SKILL.md — DSH-семантика исполнения плана: два режима контроллера, протокол ожидания через завершение хода и уведомление, ревью задачи, fix-loop, ledger ## Findings. (3) Пробный прогон в temp-репозитории: контроллер — главная сессия, implementer (flash) → reviewer (v4-pro) → fix через send_message → финальное ревью (v4-pro); отдельной пробой проверяется режим 2 (фоновый контроллер, глубина 2).

Tech Stack: bash, python3 stdlib, Node test runner (node --test), markdown, DSH 0.2.1-rc.3 (Cordis bundle, subagent, send_message, list_agents), Gitea CLI tea.

Spec: openspec/changes/dsh-sdd/ — proposal.md, design.md (источник решений), specs/dsh-sdd/spec.md (требования и сценарии).

Ветка: feat/41-dsh-sdd-spike, issue #41, worktree .claude/worktrees/sdd-spike.

Global Constraints

  • DSH 0.2.1-rc.3; версия плагинного API не заморожена, после апгрейда тесты прогоняются заново.
  • Бандл импортирует только Node builtins и локальные файлы (dsh/tests/package.test.mjs это проверяет): никаких @deepseek-ai/* импортов.
  • subagent-model-selection-settings нельзя ставить в dsh/bundle/cordis.patch.yml: строки нет в headless-профиле, включённый флаг роняет загрузку. Только overlay профиля.
  • Skill sdd ставится только в ~/.dsh/skills через bash dsh/install.sh --skills. Claude Code его не получает: roles/, hooks/, global/, install.sh (корневой), agents/ не меняются.
  • Тесты идут без DSH runtime: bash dsh/tests/run.sh и bash tests/run.sh (630/630 на момент дизайна) — зелёными должны быть оба набора.
  • Документация и тексты — по-русски, формат планов/ledger — как в этом репозитории.
  • Коммиты — с trailer Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>, force-push запрещён.
  • Маркировка: находки ревью T<n>.<k> / C-n / I-n / M-n, рулинги R-n (design #n), наблюдения O-n, замечания человека H-n; у каждой находки статус fixed <commit> / deferred / rejected <причина>.

Review Focus

  • Overlay копируют в headless-профиль → загрузка падает на «requires … in the Host scope»; overlay и PORT.md обязаны это сказать явно, а не только в design.md.
  • Skill прочитан в сессии без model selection → диспатч с provider/model молча игнорируется или падает; skill обязан деградировать на модель сессии и записать это наблюдением, а не выдавать за выполненное требование.
  • Ожидание описано как job_output/поллинг или как возврат значения subagent → инструкция врёт о платформе; ожидание — только конец хода + уведомление + list_agents.
  • Фоновый контроллер при maxDepth: 1 → subagent depth 2 exceeds maxDepth 1; skill обязан проверить глубину до диспатча и откатиться в режим 1 с рулингом.
  • Ledger без ## Findings/статусов или находка без маркера → отчёт контроллера считается ошибочным; тест skill обязан требовать разделы, а пробный прогон — показать заполненный ledger.
  • install.sh --skills с новым skill ломает счётчик «copied 1 local skills» в dsh/tests/install.test.mjs → счётчик и проверка наличия sdd обновляются в той же задаче.

Task 1: Overlay профиля и статическая проверка глубины

Files:

  • Create: dsh/subagent-models.yml
  • Create: dsh/tests/subagent-models.test.mjs
  • Modify: dsh/install.sh (check(), после проверки hook bridge)
  • Modify: dsh/PORT.md (§5 Configuration — подраздел про overlay и глубину; §7 — риск «Model tiers»; §8 — п. 4)

Interfaces:

  • Produces: файл dsh/subagent-models.yml — YAML-массив из двух записей: - id: subagent-model-selection-settings с config.enabled: true и config.allowedModels из двух пар (deepseek-official/deepseek-flash, deepseek-official/deepseek-v4-pro), затем - id: subagent с config.maxDepth: 2.

  • Produces: строки вывода check(): ok: subagent overlay (<путь>) или WARN: subagent overlay missing …; ok: subagent maxDepth=2 (<файл>) или WARN: subagent maxDepth is not 2 in any profile patch; SDD mode 2 is unavailable.

  • Consumes: ничего из других задач.

  • Step 1: Написать падающий тест dsh/tests/subagent-models.test.mjs

import assert from 'node:assert/strict'
import { spawnSync } from 'node:child_process'
import { existsSync, readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import { cleanup, tempDir, write } from './helpers.mjs'

const here = dirname(fileURLToPath(import.meta.url))
const overlay = join(here, '..', 'subagent-models.yml')
const script = join(here, '..', 'install.sh')

test('overlay enables model selection for both routes and depth 2', () => {
  assert.ok(existsSync(overlay), 'dsh/subagent-models.yml is missing')
  const text = readFileSync(overlay, 'utf8')
  assert.match(text, /id: subagent-model-selection-settings/)
  assert.match(text, /model: deepseek-flash/)
  assert.match(text, /model: deepseek-v4-pro/)
  assert.match(text, /id: subagent\n\s+config:\n\s+maxDepth: 2/)
  assert.match(text, /headless/)
})

test('install.sh --check reports the overlay and the profile depth', () => {
  const home = tempDir()
  try {
    const dshHome = join(home, '.dsh')
    const env = { ...process.env, HOME: home, DSH_HOME: dshHome }

    const missing = spawnSync('bash', [script, '--check'], { env, encoding: 'utf8' })
    assert.match(missing.stderr, /subagent maxDepth is not 2/)

    write(join(dshHome, 'profiles', 'desktop', 'cordis.patch.yml'), '- id: subagent\n  config:\n    maxDepth: 2\n')
    const present = spawnSync('bash', [script, '--check'], { env, encoding: 'utf8' })
    assert.match(present.stdout, /ok: subagent overlay/)
    assert.match(present.stdout, /ok: subagent maxDepth=2/)
  } finally {
    cleanup(home)
  }
})
  • Step 2: Прогнать тест и убедиться, что он падает

Run: node --test dsh/tests/subagent-models.test.mjs Expected: FAIL — dsh/subagent-models.yml is missing.

  • Step 3: Создать dsh/subagent-models.yml

YAML-массив с комментарием-шапкой: overlay для DSH-native SDD (#41); копировать в $DSH_HOME/profiles/desktop/cordis.patch.yml, не в бандл, потому что строки subagent-model-selection-settings нет в headless; после копирования — рестарт DSH; проверка — bash dsh/install.sh --check. Две записи из блока Interfaces, значения — дословно.

  • Step 4: Добавить проверки в dsh/install.sh

В check() после блока hook bridge: проверить наличие $ROOT/dsh/subagent-models.yml; отдельно — grep -qs 'maxDepth: 2' "$DSH_HOME"/profiles/*/cordis.patch.yml (glob не раскрылся — предупреждение, не ошибка; failed не поднимать: overlay опционален).

  • Step 5: Обновить dsh/PORT.md

§5: подраздел «Model routes and delegation depth» — как включить (скопировать dsh/subagent-models.yml в профиль, рестарт), что даёт (provider/model у subagent и subagent_fork, глубина 2), чего не делает (не в бандле; без overlay всё идёт на модели сессии). §7: в пункте «Model tiers» — два маршрута и ссылка на overlay. §8: п. 4 (SDD spike) получает статус «в работе, change dsh-sdd».

  • Step 6: Прогнать тесты

Run: node --test dsh/tests/subagent-models.test.mjs Expected: PASS (2 tests).

  • Step 7: Прогнать оба набора

Run: bash dsh/tests/run.sh && bash tests/run.sh Expected: все зелёные (если в worktree падает guard на 5 тестах — проверить ls -ld dsh/bundle/hooks, должен быть симлинк ../../hooks, O-1).

  • Step 8: Коммит
git add dsh/subagent-models.yml dsh/tests/subagent-models.test.mjs dsh/install.sh dsh/PORT.md
git commit -m "feat(dsh): overlay профиля — model selection и maxDepth 2 (#41)"

Task 2: Skill sdd — DSH-семантика исполнения плана

Files:

  • Create: dsh/skills/sdd/SKILL.md
  • Create: dsh/tests/sdd-skill.test.mjs
  • Modify: dsh/tests/install.test.mjs (ожидание «copied 2 local skills», проверка skills/sdd/SKILL.md)
  • Modify: dsh/README.md (What works / Not yet / Layout / Known limits)

Interfaces:

  • Produces: skill с frontmatter name: sdd и description: Use when executing an implementation plan in DeepSeek Harness …; текст содержит: оба режима, maxDepth, инструменты subagent/send_message/list_agents/interrupt_agent, статусы DONE/DONE_WITH_CONCERNS/NEEDS_CONTEXT/BLOCKED, маршруты deepseek-official/deepseek-flash и deepseek-official/deepseek-v4-pro, ledger с ## Findings, таблицу отличий от Claude-SDD.

  • Consumes: dsh/subagent-models.yml из Task 1 (ссылка в разделе про глубину и модели).

  • Step 1: Написать падающий тест dsh/tests/sdd-skill.test.mjs

Проверки (каждая — отдельный test):

  1. frontmatter: /^---\nname: sdd\n/, description: .+;
  2. режимы: /Режим 1/, /Режим 2/, /maxDepth: 2/ и /глубин/;
  3. инструменты: subagent, send_message, list_agents, interrupt_agent;
  4. статусы: DONE_WITH_CONCERNS, NEEDS_CONTEXT, BLOCKED;
  5. маршруты: deepseek-official/deepseek-flash, deepseek-official/deepseek-v4-pro;
  6. ledger: ## Findings, fixed <commit>, T<n>.<k>;
  7. ожидание: /закончи ход/ и /уведомлен/; НЕ содержит job_output;
  8. отличие: синхронный и асинхронный, subagent-driven-development;
  9. деградация: /модель сессии/, /не паритет/ — заголовок таблицы отличий с запретом выдавать за паритет;
  10. размер: Buffer.byteLength(text) < 12288.

Run: node --test dsh/tests/sdd-skill.test.mjs → FAIL (файла нет).

  • Step 2: Написать dsh/skills/sdd/SKILL.md

Разделы: When to use / when not (DSH-сессии; в Claude Code — исходный subagent-driven-development); два режима и правило выбора (один план — главная сессия, глубина 1; несколько параллельных планов — фоновый контроллер на план, глубина 2) + проверка глубины до первого диспатча и рулинг об откате; протокол диспатча (бриф файлом, отчёт файлом, контракт статусов, в контекст — только статус, коммиты, одна строка тестов); ожидание (конец хода, уведомление, list_agents перед каждым диспатчем, interrupt_agent для зависших, запрет job_output); ревью задачи (спека + качество) и fix-loop 5 раундов (1–3 — тот же implementer через send_message, 4–5 — свежий на тир выше, потом адъюдикация); финальное ревью ветки C-n/I-n/M-n; ledger (первая строка — путь плана, таблица конфликтов, рулинги R-n (design #n), ## Findings со статусами); маршруты моделей и деградация; таблица отличий от subagent-driven-development (синхронный Task vs асинхронный subagent, send_message, глубина по умолчанию, выбор модели, ожидание); запреты (не заявлять паритет, workflow — расширение, в первой версии не включать).

  • Step 3: Прогнать тест

Run: node --test dsh/tests/sdd-skill.test.mjs → PASS.

  • Step 4: Обновить dsh/tests/install.test.mjs

copied 1 local skills → copied 2 local skills; после проверки role проверить join(dshHome, 'skills', 'sdd', 'SKILL.md') — существует и содержит name: sdd.

  • Step 5: Обновить dsh/README.md

What works: SDD-инструкция и overlay. Not yet: убрать SDD, оставить briefing, harness-check, role-hint, harness-doctor, auto-memory, caveman. Layout: skills/sdd/SKILL.md, subagent-models.yml. Known limits: заменить строку про sonnet/haiku/opus ссылкой на overlay.

  • Step 6: Прогнать всё

Run: bash dsh/tests/run.sh && bash tests/run.sh → зелёные.

  • Step 7: Коммит
git add dsh/skills/sdd/SKILL.md dsh/tests/sdd-skill.test.mjs dsh/tests/install.test.mjs dsh/README.md
git commit -m "feat(dsh): skill sdd — асинхронный протокол исполнения плана (#41)"

Task 3: Пробный прогон 3 задач и запись результатов

Files:

  • Create: /tmp/dsh-sdd-trial* — temp-репозиторий (не входит в PR)
  • Modify: openspec/changes/dsh-sdd/design.md — раздел «Результаты пробного прогона»
  • Modify: dsh/PORT.md §8 — п. 4 закрыт ссылкой на прогон
  • Modify: этот план — отметить шаги
  • Comment: issue #41, затем PR (tea pulls create)

Interfaces:

  • Consumes: skill sdd из Task 2, overlay из Task 1 (в профиле уже включён владельцем).

  • Produces: транскрипт прогона (диспатчи, статусы, отчёты, ledger) в design.md; вывод о режимах 1 и 2.

  • Step 1: Создать temp-репозиторий и план

TRIAL="$(mktemp -d)/trial"; git init -b main, коммит README.md; git checkout -b feat/trial; файл docs/superpowers/plans/2026-10-24-trial.md — один план (require-plan разрешает правки), проект: Python-модуль src/stats.py. Три задачи: (1) mean(values) — float, ValueError на пустом списке, готовый код и тест в плане; (2) median(values) — по требованиям для чётной длины среднее двух средних; в плане намеренно оставлен дефект: return xs[len(xs) // 2], а тест в плане покрывает только нечётную длину (дефект должен найти ревьюер, не тесты); (3) describe(values) — dict {count, mean, median} через две функции. Тесты — python3 -m unittest discover -s tests. Спека прогона — SPEC.md в temp-репо: требования к mean/median/describe, включая «чётная длина — среднее двух средних».

  • Step 2: Ledger прогона

.superpowers/sdd/trial-plan/progress.md: первая строка — путь плана; таблица сканирования плана (конфликт: план Task 2 противоречит SPEC.md — рулинг R-1: следовать SPEC.md, дефект фиксировать находкой T2.1 при ревью, а не править план до диспатча); пустой ## Findings; три строки Task N: pending.

  • Step 3: Диспатч implementer'а Task 1 (режим 1)

subagent c description «trial task 1», cwd = temp-репо, provider: deepseek-official, model: deepseek-flash; промпт — brief файлом briefs/task-1.md (контекст, требования, точный код, тест, коммит), отчёт — reports/task-1.md с первой строкой-статусом; требование: python3 -m unittest discover -s tests зелёный, коммит. После вызова — закончить ход; продолжить по уведомлению.

  • Step 4: Собрать отчёт Task 1 и отправить на ревью

Прочитать reports/task-1.md, сверить коммит (git -C "$TRIAL" log --oneline) и прогон тестов; list_agents — сверка состояния; в ledger Task 1: complete. Диффпакет — review/pkg-task-1.txt (git diff main...HEAD); subagent с model: deepseek-v4-pro: ревью по SPEC.md и по качеству, находки T1.<k>, вердикт в reports/review-1.md.

  • Step 5: Task 2 — диспатч, ревью, fix-loop

Так же диспатчить Task 2 (flash, brief с кодом из плана и дефектом). Ревью (v4-pro) должно вернуть T2.1 — чётная длина медианы. Fix-раунд 1: send_message тому же implementer'у с находкой; по уведомлению — тест на чётную длину, фикс, коммит; ре-ревью скопом — новый subagent (v4-pro) с пакетом review/pkg-fix-1.txt; в ledger T2.1: fixed <commit>. Если ревьюер дефект не нашёл — зафиксировать O-1 (протокол пройден, но приёмка #41 «ревьюер находит дефект» не доказана) и повторить ревью с явным указанием проверять требование «чётная длина».

  • Step 6: Task 3 и финальное ревью ветки

Task 3 — flash, по плану; ревью — v4-pro; финальное ревью всей ветки — subagent v4-pro по полному диффу main...HEAD, находки C-n/I-n/M-n; один fix-диспатч при находках, одно скоуп-ревью.

  • Step 7: Проба режима 2 (глубина 2)

Отдельный temp-репозиторий или новая ветка в том же: subagent (flash) с промптом «ты контроллер, задиспатчь implementer'а на задачу X, дождись уведомления, верни отчёт»; контроллер обязан сам вызвать subagent и завершиться. Записать: работает / падает exceeds maxDepth / уведомление не пришло. При падении — находка O-n и вывод, что режим 2 требует поднятой глубины (overlay уже в профиле).

  • Step 8: Записать результаты

openspec/changes/dsh-sdd/design.md — раздел «Результаты пробного прогона 24.10.2026»: таблица приёмки #41 (пункт → чем доказан → статус), реальные диспатчи с моделями, найденный дефект T2.1 с коммитом фикса, ledger дословно, вывод по режимам, наблюдения O-n со статусами. dsh/PORT.md §8 п. 4 — закрыт.

  • Step 9: Проверки, коммит, PR

Run: bash dsh/tests/run.sh && bash tests/run.sh; openspec validate dsh-sdd --strict (если поддерживается). Коммит docs(dsh): пробный прогон SDD — режимы, дефект и fix-loop (#41), push, tea pulls create --base main --head feat/41-dsh-sdd-spike --title "DSH: SDD — skill, overlay, пробный прогон (#41)". Комментарий в #41 — состояние фазы и ссылка на PR.

Acceptance

Из #41: три задачи не теряются (ledger Task 1..3: complete + три коммита в temp-репо), отчёты собираются (файлы отчётов + строки ledger), ревьюер находит и проверяет хотя бы один дефект (T2.1 fixed <commit>), fix-loop завершается (ре-ревью чистое), ledger содержит ## Findings со статусами, прогон тестов зелёный, отличие от Claude-SDD указано таблицей в skill.