Imported from CybernetKZ/sdd-kit (
profiles/conversation_flow/.claude/skills/tz-implement/SKILL.md). Install upstream withnpx skills add CybernetKZ/sdd-kit --skill tz-implement. Copyright stays with the author.
Реализация change'а - фазы и СТОП-гейты
Вход - openspec/changes/tz-NNN-<slug>/ (proposal + спек-дельты + tasks.md),
прошедший /tz-review (вердикт "готово к реализации") и гриль (## Grill
заполнена). Выход - реализация, зелёные тесты, применённая спек-дельта,
обновлённый docs/DOCUMENTATION.md, серия логических коммитов, архивированный
change.
Ничего не пушить без явной просьбы пользователя.
Фаза 0 - входные условия и сверка с кодом (до любого плана)
- Прочитать change целиком +
openspec/specs/затронутых capability + прежние ТЗ и §§, на которые он ссылается (шапка-цитата,## Что затрагивается). - Проверить входные условия - при провале СТОП, не начинать:
- вердикт
/tz-reviewесть и он "готово к реализации"; ## Grillзаполнена и несёт шапку провенанса (Grilled by: ... | questions: N | plan changes: ...); на тиреdeepпровенанс обязан бытьplan-griller agent,session inlineна deep - СТОП;- тесты по Scenario'ям написаны
test-authorи RED; их нет - сначала тесты, не код. Тест, который неожиданно зелёный, - находка (поведение уже есть), а не повод "сделать его красным"; npx -y @fission-ai/openspec@1.7.0 validate --all --strictиbash scripts/sdd/check.shзелёные на входе;light-тир: гриля нет законно; RED-тест по единственному Scenario - обязателен.
- вердикт
- Проверить по коду каждый фактический пункт change'а: существуют ли названные
файлы/поля/точки расширения, реализовано ли то, что
## Whyназывает уже работающим, указывают ли якоряenforced:дельты на существующие символы. Якоря дельтыspec-lint.pyпроверяет сам (блокspec-lint: N change delta(s) checked, M with findings); нерезолвящийся - совет (note: anchor does not resolve yet: ...), гейт не валит: дельта законно может назвать символ, который change только создаст. Разобрать каждуюnote: файл создаётся этим change'ем и задача на это есть вtasks.md- ожидаемо; файл существует, а символа нет - расхождение по п. 4 (доложить, не "дописать символ, чтобы совпало"). Метаданные дельты (unknown_key,missing_id,missing_enforced,#### Scenario:под## Invariants) - уже нарушения, на входе их быть не должно. - Правило "код важнее спеки": change противоречит фактическому коду (поле
не там, механизм устроен иначе, "уже есть" отсутствует) ⇒ остановиться и
доложить расхождение пользователю, а не подгонять код под документ и не
"чинить" change молча. Change задним числом не редактируется - коррекция
решением пользователя (правка активного change'а через
/tzлибо новый номер, если этот уже архивирован). - Пункты
## Проверить перед реализацией- проверить сейчас (документация вендора, код плагина, пиновая версия); результат - в отчёт фазы 0. - Расхождения кода со спекой вне scope change'а - в
sdd-kit/docs/DEFECTS_CF.mdкак материал для тикета; молча не "чинить".
Фаза 1 - план и первый СТОП-гейт
- Разбить
tasks.mdна последовательность логических коммитов (обычно 1 коммит ≈ 1-2 §: схема+регенерация; бэкенд; API; UI+i18n; спека+документ). - СТОП-гейт: показать разбивку пользователю и дождаться подтверждения перед
началом. Отдельный СТОП-отчёт - перед каждым рискованным шагом:
alembic-миграция, правка
engine/schema.py, массовые правки, изменение поведения существующих тестов, правка кросс-репо контракта. - Кому реализовывать (таблица "тир -> конвейер -> модели" в
скилл
feature-flowплагинаcode-conventions, §1b): проходы поtasks.mdотдаются субагентуexecutor(sonnet) - строго по задачам, чужие тесты не правит, не коммитит, любое отклонение = стоп-отчёт. Диспуты сtest-author, решения "менять ли план" и финальное ревью остаются у главной сессии.
Фаза 2 - реализация
- Идти по
tasks.mdсверху вниз, отмечая- [x]по факту выполнения. - Один логический коммит на изменение; сообщение - русское, со ссылкой
"ТЗ №NN §M" (как принято в истории репо) и id change'а. Коммитит
разработчик (или главная сессия по его явной команде, после ревью) -
executorне коммитит. - Перед каждым коммитом зелёные:
PY=/opt/anaconda3/bin/python3.12 make test(lint_brand + lint_migrations + lint_imports + ruff + pytest, ~60 с);nvm use 20 && npm --prefix editor run build(включаетtsc --noEmit) - если тронут фронт; при правках только бэкенда достаточно финального коммита.
- Дом-конвенции - раздел «Конвенции» в
AGENTS.md: знать заранее, а не ловить линтами/хуками. Специфика реализации поверх них: правкаengine/schema.py⇒ сразуpython scripts/gen_ts_types.py(рукамиflow.gen.tsне трогать - заблокирует PreToolUse-хук); разделяемое состояние API - через атрибутыapi.main, не переносить. - Чужие тесты не правятся: тест выглядит неверным - вернуть его на шаг
test-authorвместе с Scenario, на который он трассирует. - Латентностные задачи (кэши, стриминг, горячий путь диалога): замерить before/after (p50/p90) на одинаковом сценарии; числа - в отчёт, в §17 и в спеку. Без замера утверждение "стало быстрее" не делается.
Фаза 3 - спека (канон) и документ (параллельно)
Порядок важен: сначала openspec - он канон, затем документ генерируется из той же дельты. Оба - в тех же коммитах, что и код.
- Применить спек-дельту в
openspec/specs/<capability>/spec.md:openspec sync-specs-путь (скилл.claude/skills/openspec-sync-specs/) или руками; обновить в затронутых Requirement маркер> Last verified: <дата> (commit <sha>)и якоряenforced:на реальные символы реализации (grep -n '<Symbol>' <path>- проверить, а не вписать). - Перенести то же изменение в
docs/DOCUMENTATION.md: затронутые §8.x, карта проекта §14, глоссарий §16, запись в §17 changelog + bump minor-версии1.NN.0(версия - в шапке документа). Текст генерируется из спек-дельты; при конфликте прав openspec. Living-spec-фрагмент pre-commit предупреждает, если код закоммичен без документа - игнорировать предупреждение нельзя. - Тесты: файл(ы) по Scenario'ям с трейсерами
# spec: <requirement-id> / <scenario>; добавить строку в картуtests/README.md. - Финальный прогон целиком зелёный:
Вторая строка не дубль первой: внутриPY=/opt/anaconda3/bin/python3.12 make test nvm use 20 && npm --prefix editor run build bash scripts/sdd/check.sh # включает openspec validate --strict и spec-lint (последний advisory) SPEC_LINT_STRICT=1 python3 .claude/scripts/spec-lint.py # здесь - как гейт: дельта уже в канонеsdd-checkspec-lint выходит с 0 и его находки - лишь отчёт, а после применения дельты в канон метаданные и якоря обязаны быть чистыми (строгий режим покрывает и канон, и ещё не заархивированную дельту).noteпо якорям к этому моменту быть не должно: код написан, символы существуют. Осталась - либо якорь врёт, либо задача не выполнена.
Фаза 4 - ревью, приёмка, архивация
- Ревьюеры на диффе:
backend-reviewer, плюсdatabase-reviewerпри правках SQL/ORM/миграций. CRITICAL/HIGH в scope - исправить; вне scope -TODO/NOTEсо ссылкой на ТЗ, scope не расширять. После правок - перепрогнать тесты. - Пройти вручную QA-Scenario'и на локальном/стейдж-контуре.
- Отметить все
- [x]вtasks.md; каждый критерий приёмки - подтверждён фактом (тест, замер, живая проверка), а не "сделано". - Архивировать change - скилл
.claude/skills/openspec-archive-change/(openspec/changes/tz-NNN-*->changes/archive/tz-NNN-*), после того как спека применена и документ обновлён.
Финальный отчёт
Что реализовано по каждому пункту tasks.md (с номерами); чем закрылись пункты
## Проверить перед реализацией; результаты замеров latency; список коммитов;
что применено в openspec/specs/ и какие §§ документа + версия обновлены;
дефекты, отправленные в DEFECTS_CF.md. Расхождения и осознанные отступления от
change'а - явно, а не между строк. Не пушить - только по явной просьбе.