# 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` + доки.