feat(dsh): overlay профиля — model selection и maxDepth 2 (#41)
dsh/subagent-models.yml — opt-in overlay: subagent-model-selection-settings с маршрутами deepseek-flash/deepseek-v4-pro и subagent.maxDepth: 2. В бандл не входит: строки нет в headless, включённый флаг ломает загрузку. install.sh --check сообщает overlay и находит maxDepth: 2 в патче профиля. PORT.md §5 — как включить и что это даёт; §7/§8 обновлены. Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
This commit is contained in:
parent
ee0d876f6b
commit
2bee63d305
241
docs/superpowers/plans/2026-10-24-dsh-sdd.md
Normal file
241
docs/superpowers/plans/2026-10-24-dsh-sdd.md
Normal file
@ -0,0 +1,241 @@
|
||||
# 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`
|
||||
|
||||
```js
|
||||
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: Коммит**
|
||||
|
||||
```bash
|
||||
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: Коммит**
|
||||
|
||||
```bash
|
||||
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.
|
||||
37
dsh/PORT.md
37
dsh/PORT.md
@ -162,6 +162,32 @@ for the repository layout:
|
||||
bootstrapMaxBytes: 65536
|
||||
```
|
||||
|
||||
### Model routes and delegation depth
|
||||
|
||||
SDD needs two things the default profile does not give: a model choice for
|
||||
`subagent` and a second level of delegation for a background controller.
|
||||
`dsh/subagent-models.yml` is the opt-in overlay for both:
|
||||
|
||||
```bash
|
||||
# 1. copy the two entries into the profile patch (desktop is Electron-managed)
|
||||
open -e ~/.dsh/profiles/desktop/cordis.patch.yml # append dsh/subagent-models.yml
|
||||
# 2. restart DSH, then check
|
||||
bash dsh/install.sh --check # "ok: subagent maxDepth=2 (...)"
|
||||
```
|
||||
|
||||
After the restart the `subagent` and `subagent_fork` schemas accept
|
||||
`provider`, `model`, `reasoning_effort`, and a background controller subagent
|
||||
can dispatch an implementer. Routes measured in 0.2.1-rc.3:
|
||||
`deepseek-official/deepseek-flash` (transcription and mechanics) and
|
||||
`deepseek-official/deepseek-v4-pro` (integration and every review). Without the
|
||||
overlay the agent runs everything on the session model and at depth 1; the
|
||||
`sdd` skill must say so in its report instead of pretending the routes exist.
|
||||
|
||||
The overlay stays out of `dsh/bundle/cordis.patch.yml` on purpose: the
|
||||
`subagent-model-selection-settings` row exists in the web/desktop profile and is
|
||||
absent in headless, and enabling it from the bundle would break headless boot
|
||||
with "requires ... in the Host scope".
|
||||
|
||||
`bootstrapSkillPath` resolution order: explicit path, `DSH_SUPERPOWERS_SKILL`,
|
||||
`~/.dsh/skills`, `~/.agents/skills`, the newest
|
||||
`~/.claude/plugins/cache/claude-plugins-official/superpowers/*/`, then
|
||||
@ -271,8 +297,9 @@ profile was removed; the real `desktop` profile was not touched.
|
||||
- **Subagent bootstrap.** `isSubagent` probes common fields; if none are present
|
||||
on this version, the bootstrap reaches children too. The skill's
|
||||
`<SUBAGENT-STOP>` makes that harmless but token-expensive.
|
||||
- **Model tiers.** `sonnet`/`haiku`/`opus` are not DSH models. Map them to live
|
||||
provider/model routes before porting the SDD text.
|
||||
- **Model tiers.** `sonnet`/`haiku`/`opus` are not DSH models. The port uses two
|
||||
live routes (`deepseek-flash`, `deepseek-v4-pro`) from the opt-in overlay in
|
||||
`dsh/subagent-models.yml`; without it every dispatch runs on the session model.
|
||||
- **`~/.claude` dependence.** `dsh/install.sh --skills --roles` copies skills
|
||||
and roles into `~/.dsh`; the bootstrap and `/role` prefer those copies, and
|
||||
the Claude cache/roles are fallbacks. An existing installation must rerun
|
||||
@ -291,8 +318,10 @@ profile was removed; the real `desktop` profile was not touched.
|
||||
2. Add `harness-check` and optional `role-hint` as non-blocking pre-step
|
||||
injections.
|
||||
3. Build `briefing` as an agent preset (read-only tools + model route).
|
||||
4. SDD spike: async controller (`subagent` + `send_message`, `maxDepth: 2`) for
|
||||
one plan, or a `workflow`-based executor; measure which fits the harness.
|
||||
4. SDD: change `dsh-sdd` — the `sdd` skill (async controller, reports, review,
|
||||
fix-loop, ledger) plus the overlay in §5; proven by a three-task trial run in
|
||||
a temporary repository. See
|
||||
`openspec/changes/dsh-sdd/design.md`.
|
||||
5. Enable CodeGraph MCP by default when the binary is present; update role and
|
||||
project instructions to `mcp__codegraph__codegraph_explore`.
|
||||
6. Port `harness-doctor` checks to DSH paths.
|
||||
|
||||
@ -102,6 +102,24 @@ check() {
|
||||
echo "FAIL: hook bridge is missing (is dsh/bundle/hooks a symlink to ../../hooks?)" >&2
|
||||
failed=1
|
||||
fi
|
||||
if [ -f "$ROOT/dsh/subagent-models.yml" ]; then
|
||||
echo "ok: subagent overlay ($ROOT/dsh/subagent-models.yml)"
|
||||
else
|
||||
echo "WARN: subagent overlay missing; SDD runs on the session model at depth 1" >&2
|
||||
fi
|
||||
local patch found=0
|
||||
for patch in "$DSH_HOME"/profiles/*/cordis.patch.yml; do
|
||||
[ -f "$patch" ] || continue
|
||||
if grep -qs 'maxDepth: 2' "$patch"; then
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$found" = 1 ]; then
|
||||
echo "ok: subagent maxDepth=2 ($patch)"
|
||||
else
|
||||
echo "WARN: subagent maxDepth is not 2 in any profile patch; SDD mode 2 is unavailable" >&2
|
||||
fi
|
||||
if [ -f "$DSH_HOME/skills/using-superpowers/SKILL.md" ]; then
|
||||
echo "ok: dsh skills ($DSH_HOME/skills)"
|
||||
elif superpowers_skills >/dev/null 2>&1; then
|
||||
|
||||
32
dsh/subagent-models.yml
Normal file
32
dsh/subagent-models.yml
Normal file
@ -0,0 +1,32 @@
|
||||
# Opt-in overlay for DSH-native SDD (issue #41).
|
||||
#
|
||||
# Copy these two entries into $DSH_HOME/profiles/desktop/cordis.patch.yml, then
|
||||
# restart DSH (the plugin page must reload the profile). Verify with:
|
||||
# bash dsh/install.sh --check
|
||||
# # in a new session the `subagent` tool schema shows provider/model/reasoning_effort
|
||||
#
|
||||
# Do NOT add them to dsh/bundle/cordis.patch.yml: the
|
||||
# `subagent-model-selection-settings` row exists in the web/desktop profile and
|
||||
# is absent in headless, so enabling it in the bundle breaks headless boot
|
||||
# ("requires ... in the Host scope").
|
||||
#
|
||||
# What it unlocks:
|
||||
# - `subagent` and `subagent_fork` accept provider/model/reasoning_effort,
|
||||
# so an implementer can run on a cheaper route than the reviewer;
|
||||
# - `subagent.maxDepth: 2`, so a background controller subagent (depth 1)
|
||||
# can dispatch implementers (depth 2).
|
||||
#
|
||||
# Routes measured in DSH 0.2.1-rc.3:
|
||||
# deepseek-official/deepseek-flash - transcription and mechanics
|
||||
# deepseek-official/deepseek-v4-pro - integration and every review
|
||||
- id: subagent-model-selection-settings
|
||||
config:
|
||||
enabled: true
|
||||
allowedModels:
|
||||
- provider: deepseek-official
|
||||
model: deepseek-flash
|
||||
- provider: deepseek-official
|
||||
model: deepseek-v4-pro
|
||||
- id: subagent
|
||||
config:
|
||||
maxDepth: 2
|
||||
39
dsh/tests/subagent-models.test.mjs
Normal file
39
dsh/tests/subagent-models.test.mjs
Normal file
@ -0,0 +1,39 @@
|
||||
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)
|
||||
}
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user