8.8 KiB
dsh-prestep Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use the
sddskill (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
- Инъекции бандла не принимаются за первое пользовательское сообщение (фильтр маркеров).
- Автономный раунд без нового сообщения — role-hint не стреляет.
- cwd вне git-репозитория — harness-check молчит.
- Подкаталог репозитория (cwd = /dsh) — upward-walk находит корень, ложной подсказки нет.
- 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).