claude-harness/docs/superpowers/plans/2026-10-25-dsh-prestep.md

84 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# dsh-prestep Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use the `sdd` skill (DSH). Steps use checkbox syntax.
**Goal:** Портировать SessionStart-хуки harness-check и role-hint в DSH как неблокирующие agent/pre-step инъекции + закрыть follow-ups #62 (T2.1, T3.4, O-2).
**Architecture:** `dsh/bundle/lib/prestep.js` — чистые функции (detectAdoption с upward-walk, detectRole по ключевым словам первого пользовательского сообщения, тексты инъекций); общий хелпер видимости `isInjectionVisible` (рефакторинг из isBootstrapVisible); wiring в index.js (конфиг harnessCheck/roleHint, гейт — `typeof ctx.on === 'function'`).
**Tech Stack:** Node builtins; тесты node:test; bash для install.sh-правки.
**Spec:** `openspec/changes/dsh-prestep/` (proposal.md + design.md, D-1…D-10).
**Models:** Task 1, 3, 4 — deepseek-flash; Task 2 — deepseek-v4-pro; ревью — v4-pro.
## Global Constraints
- Node builtins only; package.test.mjs enforcement обновляется для новых файлов.
- Инъекции неблокирующие; reject/abort — пропуск; сабагенты — пропуск (как bootstrap).
- Маркер `<!-- DSH-HARNESS-PRESTEP:<hash> -->`; общая видимость через isInjectionVisible.
- Роль-ключевики ровно из AGENTS.md (admin: jira, гант, спринт; qa: стенд, прогон, скриншот, макет; analyst: тз, oq, спека, методика; dev: срез, issue, pr, тест, миграция); `pr` — отдельным словом.
- Вопрос с четырьмя вариантами — текст из design.md D-7.
- Префикс инъекций `[dsh-harness]` (D-10; фильтр знает и `[claude-harness]`).
- CC-сторона (hooks/) не трогается.
## Review Focus
1. Инъекции бандла не принимаются за первое пользовательское сообщение (фильтр маркеров).
2. Автономный раунд без нового сообщения — role-hint не стреляет.
3. cwd вне git-репозитория — harness-check молчит.
4. Подкаталог репозитория (cwd = <repo>/dsh) — upward-walk находит корень, ложной подсказки нет.
5. bootstrap:false — инъекции живут (гейт на ctx.on, не на bootstrapOk).
---
### Task 1: prestep.js — чистые функции
**Files:** Create `dsh/bundle/lib/prestep.js`, `dsh/tests/prestep.test.mjs`.
**Interfaces:**
- `detectAdoption(cwd) -> {adopted:boolean, root:string|null, missing:string[]}` — upward-walk: ближайший каталог с `.git` (или root ФС); сигналы: `openspec/`, `.codegraph/`, `## OpenSpec и superpowers` в `CLAUDE.md` (без `.claude/code-paths`, D-9); вне git → `{adopted:true, missing:[]}` (молчим).
- `buildHarnessCheckText(root, missing) -> string` — DSH-нативный текст (D-9): `[dsh-harness] Проект <root> не подключён к обвязке: нет: … . Предложи владельцу настройку: openspec init --tools agents, codegraph init и секцию «OpenSpec и superpowers» в CLAUDE.md.`.
- `detectRole(firstUserText) -> 'dev'|'admin'|'analyst'|'qa'|null`.
- `buildRoleHintText(role|null) -> string` — `[dsh-harness] Роль сессии: <r>. Вызови skill role. Если не так — скажи.` или вопрос с четырьмя вариантами (D-7).
- `isHarnessMessage(text) -> boolean` — текст начинается с `<!-- DSH-HARNESS-` или содержит `[dsh-harness]`/`[claude-harness]` (оба префикса до обновления AGENTS.md, D-10).
- `makePrestepMarker(text) -> {marker, body}`.
**Tests (TDD):** detectAdoption в temp-дереве (adopted repo, missing-openspec repo, subdir cwd, non-repo cwd); detectRole по каждому слову + `pr` как слово/не слово; buildRoleHintText оба варианта; isHarnessMessage на bootstrap-тексте; маркер уникален.
- [ ] Step 1: падающие тесты → Step 2: FAIL → Step 3: реализация → Step 4: PASS + `bash dsh/tests/run.sh` (161/0) → Step 5: коммит `feat(dsh): prestep — detectAdoption/detectRole/тексты инъекций (#43)`.
### Task 2: wiring + isInjectionVisible рефакторинг
**Files:** Modify `dsh/bundle/lib/bootstrap.js` (переименование экспорта + совместимый алиас), `dsh/bundle/index.js`, `dsh/tests/bootstrap.test.mjs` (imports), `dsh/tests/prestep.test.mjs` (apply-тесты).
**Interfaces:**
- `isInjectionVisible(agent, messages, marker)` — та же логика, что isBootstrapVisible; старый экспорт остаётся алиасом (обратная совместимость).
- index.js: `DEFAULTS += {harnessCheck:true, roleHint:true}`; в pre-step после bootstrap-блока: `const onOk = typeof ctx.on === 'function'`; harnessCheck && onOk → detectAdoption(sessionCwd) → не adopted → инъекция (маркер, isInjectionVisible); roleHint && onOk → первое user-сообщение текущего шага (source.kind user, не isHarnessMessage) → detectRole → инъекция.
**Tests:** apply с fake ctx: инъекция harness-check при missing-сигналах; молчание при adopted/non-repo; role-hint при user-сообщении с ключевиком; вопрос без ключевика; без нового user-сообщения — тишина; маркерные сообщения не считаются первыми; bootstrap:false + harnessCheck:true — инъекции работают (onOk прямой).
- [ ] Steps TDD → коммит `feat(dsh): wiring harness-check/role-hint в pre-step, isInjectionVisible (#43)`.
### Task 3: follow-ups #62
**Files:** Modify `dsh/tests/openspec.test.mjs` (T2.1), `dsh/install.sh` (O-2 WARN), `dsh/tests/install.test.mjs`, `dsh/skills/sdd/SKILL.md` (T3.4 + пин в install.test.mjs).
**Interfaces:**
- T2.1: негативный тест --check без openspec: вместо фиксированного PATH — временный каталог-сторож с symlink-ами на нужные бинарники без openspec (или skip-if-present; выбрать первое).
- O-2: install.sh WARN «DSH_HOME указывает на существующий каталог при нестандартном HOME» в начале install_skills/install_roles; тест с temp HOME + реальный DSH_HOME → WARN.
- T3.4: в sdd SKILL.md добавить предложение в протокол диспатча: «шаг „прогони тест и убедись, что он падает“ обязателен ДО кода»; пин текста в install.test.mjs (или sdd-skill.test.mjs — файл в списке брифа).
- [ ] Steps TDD → коммит `fix(dsh): #62 — PATH-изоляция теста, WARN DSH_HOME, TDD-порядок в sdd (#62)`.
### Task 4: спека-дельта session-prestep + доки
**Files:** Create `openspec/changes/dsh-prestep/specs/session-prestep/spec.md`; Modify `dsh/README.md`, `dsh/PORT.md`, `dsh/bundle/dsh-tools.md` (упомянуть request_approval — T1.3 из #77), `openspec/changes/dsh-prestep/design.md` (статусы), `openspec/specs/approval-gates/spec.md` (T1.5 из #77 — формулировка ошибки диалога).
**Requirements:** ADDED — harness-check инъекция (сигналы, upward-walk, вне-git молчание, неблокируемость, конфиг), role-hint инъекция (триггер/фильтр/ключевики/тексты, раз за сессию), общая видимость инъекций, #62-фиксы (T2.1 PATH, O-2 WARN, T3.4 текст); строка про request_approval в dsh-tools.md (T1.3); формулировка «ошибка диалога» в approval-gates (T1.5).
- [ ] Steps: `openspec validate dsh-prestep --strict` → valid; `bash dsh/tests/run.sh`; коммит `docs(openspec): спека session-prestep, доки (#43, #62)`.
## Предусловия
- Ветка: `feat/43-dsh-prestep` (require-plan сопоставляет ветку по строке в плане; строка добавляется ДО plan-аппрува — A4).
- baseline `bash dsh/tests/run.sh` = 161/0 на ветке; python3/git/node в PATH; сеть не нужна.
- Гейты активны: план исполняется после `/approve dsh-prestep plan` (это и есть приёмка #59).