From 0d5d621fdcd10136ba0bfc5b5ada91941e41fa77 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 25 Oct 2026 05:57:46 +0400 Subject: [PATCH] =?UTF-8?q?docs(openspec):=20change=20dsh-prestep=20?= =?UTF-8?q?=E2=80=94=20proposal=20=D0=B8=20design=20(#43,=20#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openspec/changes/dsh-prestep/.openspec.yaml | 2 + openspec/changes/dsh-prestep/design.md | 73 +++++++++++++++++++++ openspec/changes/dsh-prestep/proposal.md | 60 +++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 openspec/changes/dsh-prestep/.openspec.yaml create mode 100644 openspec/changes/dsh-prestep/design.md create mode 100644 openspec/changes/dsh-prestep/proposal.md diff --git a/openspec/changes/dsh-prestep/.openspec.yaml b/openspec/changes/dsh-prestep/.openspec.yaml new file mode 100644 index 0000000..7ccf7c3 --- /dev/null +++ b/openspec/changes/dsh-prestep/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-25 diff --git a/openspec/changes/dsh-prestep/design.md b/openspec/changes/dsh-prestep/design.md new file mode 100644 index 0000000..1c0cdfa --- /dev/null +++ b/openspec/changes/dsh-prestep/design.md @@ -0,0 +1,73 @@ +# Design: dsh-prestep — harness-check и role-hint через agent/pre-step + +Issue: #43 (+#62). Статус: черновик до builder-check; утверждение — +`/approve dsh-prestep design`. + +## Контекст + +CC-хуки harness-check/role-hint — SessionStart; в DSH аналог — инъекции +`agent/pre-step` (уже используем для superpowers-bootstrap). Гейты #59 +живые: этот change идёт первым по гейтованному циклу (acceptance #59). + +## Механика + +Обе инъекции — раз за сессию, с маркером `<-- DSH-HARNESS-PRESTEP:...>` +и тем же механизмом видимости, что у bootstrap (`isBootstrapVisible` +переименован в общий `isInjectionVisible(agent, messages, marker)`). +Порядок в pre-step: другие инъекции → harness-check → role-hint (обе +неблокирующие; reject/abort — пропуск; сабагенты — пропуск, как +bootstrap). + +### harness-check + +- Сигнал подключения: `CLAUDE.md` или `AGENTS.md` в корне cwd содержит + `OpenSpec и superpowers` ИЛИ существует `openspec/` ИЛИ + `.claude/code-paths` ИЛИ `CLAUDE.harness-section.md`. Нет — инъекция: + «[claude-harness] Проект не подключён к обвязке: предложи владельцу + `adopt-project.sh` или спроси, нужна ли обвязка». Не блокирует. +- cwd — `sessionCwd` (та же резолюция, что у гейтов: workingDirectory → + process.cwd()). + +### role-hint + +- Триггер: первое пользовательское сообщение сессии (в `decision.messages` + ищем message с `source.kind === 'user'` и текстом; до первого такого — + инъекции нет). +- Ключевые слова (порядок приоритета, как в AGENTS.md): + - admin: `jira`, `грант`, `гант`, `спринт`; + - qa: `стенд`, `прогон`, `скриншот`, `макет`; + - analyst: `тз`, `oq`, `спека`, `методика`; + - dev: `срез`, `issue`, `pr`, `тест`, `миграция`. + Совпадение — инъекция `[claude-harness] Роль сессии: . Вызови + skill role. Если не так — скажи.` Нет — инъекция вопроса с четырьмя + вариантами (текст — как в AGENTS.md). +- Матчинг: нижний регистр, подстроки по границам слов (русские слова — + подстрока в нижнем регистре; `pr` — только как отдельное слово). + +## Decisions made without discussion + +| # | Решение | Обоснование | Цена ошибки | +|---|---|---|---| +| D-1 | Роль определяется по первому сообщению (не по заголовку — его в DSH нет) | Ровно то правило AGENTS.md, которое модель сейчас исполняет «по памяти»; переносим в технику | Ложная подсказка роли при неоднозначном сообщении — поправима (`/role`), не блокирует | +| D-2 | harness-check — только подсказка, без HARNESS_AUTO_ADOPT | YAGNI; авто-подключение — отдельная фича при запросе | Сессия в неподключённом проекте продолжает работу — как и сейчас | +| D-3 | Общий хелпер инъекций (рефакторинг bootstrap) без изменения поведения bootstrap | Два новых pre-step не должны дублировать маркер/дедуп | Регрессия bootstrap — страхуется существующими тестами bootstrap | +| D-4 | #62-пункты едут задачами этого change (не отдельными фичами) | Мелкие, один PR-цикл дешевле трёх | Смешивание тем в одном PR — компенсируется отдельными задачами плана | +| D-5 | Конфиг-ключи harnessCheck/roleHint — по умолчанию true, гейтятся bootstrapOk (нужен ctx.on) | Симметрия с bootstrap; без pre-step обе инъекции невозможны | Нет | + +## Тесты (идеи для плана) + +- pure: detectAdoption(files), detectRole(firstUserText) → role|null, + buildRoleHintText(role), buildHarnessCheckText(), маркер-дедуп; +- wiring: apply с fake ctx — инъекции появляются при наличии + пользовательского сообщения, один раз, пропускаются для сабагентов; +- T2.1: негативный тест openspec — PATH-изоляция (временный каталог без + openspec-бинарника); +- O-2: install.sh WARN при DSH_HOME→существующий каталог + нестандартный + HOME (тест в install.test.mjs); +- T3.4: пин текста в sdd-скилле («шаг „тест падает“ обязателен»). + +## На потом (в план) + +- Разбивка: Task 1 prestep.js (harness-check+role-hint pure) → Task 2 + wiring+bootstrap-рефакторинг → Task 3 #62 (T2.1/O-2/T3.4) → Task 4 + спека-дельта `session-prestep` + доки. diff --git a/openspec/changes/dsh-prestep/proposal.md b/openspec/changes/dsh-prestep/proposal.md new file mode 100644 index 0000000..e9befe4 --- /dev/null +++ b/openspec/changes/dsh-prestep/proposal.md @@ -0,0 +1,60 @@ +# Proposal: dsh-prestep — harness-check и role-hint через agent/pre-step + +Issue: #43 (+#62 follow-ups). Источники: роадмап #48 (закрыт), дизайн #69, +AGENTS.md (правило первого сообщения), архив #42 (§6 приёмка). + +## Why + +У Claude Code два SessionStart-хука: `harness-check.sh` (проект не подключён +→ предложить adopt) и `role-hint.sh` (подсказка роли по заголовку сессии). +В DSH их нет (#43): сессия в неподключённом проекте молча работает без +обвязки, а выбор роли держится только на дисциплине модели (первое правило +AGENTS.md). Плюс три мелких follow-ups из #42 (#62: T2.1 — PATH в негативном +тесте, T3.4 — TDD-порядок в брифах, O-2 — изоляция HOME/DSH_HOME в брифах). + +## What Changes + +1. **harness-check как pre-step**: один раз за сессию (маркер-дедуп, как у + bootstrap) проверяем, что проект подключён (в `CLAUDE.md`/`AGENTS.md` + корня cwd есть секция обвязки «OpenSpec и superpowers» или файлы + `openspec/`/`.claude/code-paths`); нет — неблокирующая инъекция: + «проект не подключён к обвязке; предложи `adopt-project.sh` или спроси + владельца». Конфиг `harnessCheck: true`. +2. **role-hint как pre-step**: на первом пользовательском сообщении — + ключевые слова из AGENTS.md (Jira/Гант/спринт → admin; стенд/прогон/ + скриншот/макет → qa; ТЗ/OQ/спека/методика → analyst; срез/issue/PR/ + тест/миграция → dev) → инъекция `[claude-harness] Роль сессии: ` с + указанием вызвать `skill role`; нет совпадения — инъекция вопроса с + четырьмя вариантами. Один раз за сессию. Конфиг `roleHint: true`. + Заголовка сессии в DSH нет — сигнал берём из первого сообщения + (ровно то правило, что уже написано в AGENTS.md). +3. **Follow-ups #62** (задачами этого же change): + - T2.1/M-2: негативный тест `--check` без openspec — изоляция PATH + вместо фиксированного `bin:/usr/bin:…`; + - T3.4: sdd-skill и шаблоны брифов — «шаг „тест падает“ обязателен до + кода» формулируется жёстче; + - O-2: брифы/рецепты изолируют и HOME, и DSH_HOME; `install.sh` + предупреждает, когда DSH_HOME указывает на существующий каталог при + нестандартном HOME. +4. Обе инъекции используют общую маркер/видимость-машинерию bootstrap + (выносим хелперы, поведение bootstrap не меняется). + +## Impact + +- Affected: `dsh/bundle/lib/prestep.js` (новое), `dsh/bundle/lib/bootstrap.js` + (рефакторинг хелперов), `dsh/bundle/index.js` (wiring, аддитивно), + `dsh/skills/sdd/SKILL.md`, `dsh/install.sh` (WARN O-2), + `dsh/tests/openspec.test.mjs` (T2.1), тесты prestep, спека-дельта + (capability `session-prestep`), README/PORT. +- Не трогаем: CC-сторону (хуки harness-check.sh/role-hint.sh остаются), + гейты, bootstrap-инъекцию. +- Breaking: нет (обе инъекции — неблокирующие; конфиг отключает). + +## Non-goals + +HARNESS_AUTO_ADOPT (авто-подключение) — потом, при запросе; портирование +`briefing` (#45) — отдельно; анализ заголовка сессии (в DSH его нет). + +## Открытые вопросы + +Нет — решения в design.md; владелец утверждает через `/approve dsh-prestep design`.