Agent Dev 101

Модуль 15 · Урок 15.10

Урок 15.10. Написание, ревью и редактирование изменений

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. Часть 1. Написание сильных требований и сценариев
  4. Часть 2. Двухминутное ревью плана до кода
  5. Часть 3. Редактирование изменения
  6. Практика
  7. Краткое резюме
  8. Вопросы для самопроверки
  9. Что дальше
  10. Источники

Зачем это нужно

К этому моменту в модуле разобран весь цикл работы с изменением: урок 15.3 ввел ментальную модель specs, changes и дельт, уроки 15.7-15.9 - explore-режим, workflow-паттерны и сквозные примеры от начала до конца. Но цикл /opsx:propose → /opsx:apply → /opsx:archive приносит пользу ровно настолько, насколько хороши артефакты, которые сгенерировал агент, и насколько внимательно вы их читаете и правите.

Этот урок закрывает три практических навыка, каждый своим разделом:

  • написание - что делает требование и сценарий сильными, как правильно выбрать тип дельты и размер самого изменения;
  • ревью - двухминутная проверка drafted-плана до написания кода: что открыть, в каком порядке, какие «красные флаги» искать;
  • редактирование - как править артефакты уже после начала работы, как вернуться к плану из середины реализации и как примирить ручные правки кода со спецификацией.

Все три исходных документа документации описывают одну и ту же рабочую реальность с разных сторон: писать сильные спецификации имеет смысл, только если вы умеете заметить слабое место на ревью, а заметив - быстро исправить. Поэтому материал объединен в один урок, а повторы между документами устранены.

Это continuation обзора из урока 2.10: там OpenSpec появился как инструмент на карте SDD-подходов, здесь разобран его самый трудоемкий на практике слой - качество требований.

Основная идея

Спецификации в OpenSpec - это обычный Markdown, который агент готовит по вашему описанию, а вы доводите до состояния «этому можно доверять». Качество здесь - не врожденное свойство агента, а результат короткого цикла: черновик → внимательное чтение → правка → еще черновик.

Ревью бывает ровно два раза за жизнь изменения, и первое - самое ценное:

flowchart LR P["/opsx:propose"] --> R1["Ревью плана<br>(до кода)"] R1 -->|"требует правок"| E["Правка артефактов"] E --> R1 R1 -->|"план ок"| A["/opsx:apply"] A --> V["Ревью кода<br>/opsx:verify"] V -->|"расхождения"| S["Синхронизация<br>кода и specs"] S --> V V -->|"ок"| AR["/opsx:archive"]

Ставка простая: заметить неверный поворот в плане на один абзац почти бесплатно, а в трехстах строках кода - нет. Все остальное в этом уроке - детализация того, что именно смотреть в каждой точке и как исправлять найденное.

Часть 1. Написание сильных требований и сценариев

Спецификацию редко пишут с чистого листа: вы описываете изменение обычным языком, /opsx:propose готовит черновик требований и сценариев, а затем вы делаете его хорошим. Этот раздел - о том, как выглядит «хороший» и как направить агента к нему.

Спецификация - это поведение, а не код

Спецификация говорит, что система делает, в терминах, которые может проверить кто угодно, - а не как она устроена внутри. Она состоит из требований (утверждений о поведении) и сценариев (конкретных примеров, которые их доказывают):

markdown
### Requirement: Session Timeout
The system SHALL expire a session after 30 minutes of inactivity.

#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 30 minutes pass with no activity
- THEN the session is invalidated and the user must re-authenticate

Анатомия примера по элементам:

Элемент Роль в формате
### Requirement: <имя> заголовок требования; имя называет поведение, а не задачу или функцию кода
The system SHALL … само утверждение о поведении с ключевым словом силы (SHALL/MUST/SHOULD/MAY)
#### Scenario: <имя случая> заголовок сценария; имя называет конкретный случай
GIVEN … начальное состояние - предусловия, в которых находится система
WHEN … действие или событие, которое запускает проверяемое поведение
THEN … наблюдаемый результат - то, что можно проверить

Каждая связка GIVEN / WHEN / THEN устроена так, чтобы ее можно было превратить в автоматический тест без чтения кода.

«Как» - очередь, библиотека, схема таблицы - остается в design.md или в коде. Когда поведение и реализация смешаны в одном требовании, требование перестает быть проверяемым и начинает устаревать в момент, когда меняется код.

Что делает требование сильным

Хорошее требование - одно поведение, сформулированное настолько ясно, что его можно передать другому человеку на тестирование:

  • Одно утверждение - один SHALL/MUST. Если в требовании три придаточных «а также», это действительно три требования. Разделите их.
  • Наблюдаемость. Человек вне кода должен суметь определить, выполняется ли требование. «The system SHALL show an error banner when the upload exceeds 10 MB» - наблюдаемо. «The system SHALL handle large uploads gracefully» - нет.
  • Правильная сила утверждения. OpenSpec использует ключевые слова RFC 2119, и они означают разное:
Ключевое слово Значение
MUST / SHALL жесткое требование, без вариантов
SHOULD сильная рекомендация с возможностью обоснованного исключения
MAY действительно необязательное

По умолчанию используйте MUST/SHALL. SHOULD - только когда вы действительно имеете в виду «если нет веской причины поступить иначе».

Итоговый тест требования: сможет ли тестировщик, никогда не видевший код, определить, прошло оно или нет? Если нет - требование нужно заострить.

Слабые и сильные формулировки рядом, на примерах из документации:

Слабо Сильно Почему
The system SHALL handle large uploads gracefully The system SHALL show an error banner when the upload exceeds 10 MB первое не наблюдаемо: «gracefully» не проверить; второе дает конкретное условие и конкретный результат
The system SHALL be fast требование с измеримой границей поведения «fast» нельзя ни построить, ни протестировать - что такое «fast»?
три «а также» в одном утверждении три отдельных требования с одним SHALL каждое одно утверждение - одно поведение; иначе требование нельзя проверить целиком

Что делает сценарий хорошим

Сценарии - место, где требование отрабатывает свою ценность. Каждый - конкретная связка GIVEN / WHEN / THEN, которая могла бы стать автоматическим тестом:

  • Сценарий проверяет свое требование. Сценарий, который пересказывает требование другими словами, не проверяет ничего. Делайте его конкретной ситуацией с конкретным исходом.
  • Покрывайте случаи, которые важны, а не только happy path. Успешный логин написать легко. Пустой ввод, истекший токен, второй клик, то, что идет не так, - именно там живут баги и именно там сценарий дороже всего.
  • Называйте случай в заголовке. «Scenario: Rejects an expired token» мгновенно показывает ревьюеру, что покрыто; «Scenario: Test 2» - нет.

Разница видна уже на уровне заголовков:

markdown
#### Scenario: Test 2
(ревьюеру приходится читать тело, чтобы понять, что проверяется)

#### Scenario: Rejects an expired token
(покрытый случай виден при беглом просмотре списка сценариев)

Заголовки сценариев - это оглавление покрытия: по одному списку заголовков ревьюер уже видит, какие случаи учтены, а какие выпали.

Полезная привычка: перед тем как одобрить изменение, спросите себя, какой единственный случай было бы больнее всего обнаружить сломанным - и убедитесь, что какой-то сценарий называет его.

Выбор типа дельты: ADDED, MODIFIED, REMOVED

Изменение описывает свои правки спецификаций тремя типами секций. Правильный выбор держит заархивированные спецификации честными:

Секция дельты Когда используется Что делает архивация
## ADDED Requirements новое поведение, которого раньше не было дописывается в основную спецификацию
## MODIFIED Requirements существующее поведение меняется заменяет старую версию целиком
## REMOVED Requirements поведение уходит удаляется из спецификации

В MODIFIED включайте полную новую версию требования - короткая заметка о том, что изменилось, помогает ревьюеру. В REMOVED добавьте строку о причине.

Ошибки выбора заметны не сразу, но стоят дорого: пометить существующее изменение как ADDED - и в спецификации окажутся два конкурирующих требования; описать новое поведение как MODIFIED - и окажется, что заменять нечего. Если сомневаетесь - откройте текущую спецификацию и посмотрите, есть ли там уже это требование.

Секция Purpose при создании новой возможности

Когда дельта создает возможность (capability), которой еще не существует, откройте ее секцией ## Purpose - одним-двумя предложениями о том, для чего возможность нужна:

markdown
## Purpose

Lets the user switch the app between light and dark themes,
following the OS preference on first load.

При архивации эта секция становится Purpose основной спецификации, которую создает архивация. Пропустите ее - получите заглушку TBD, которую придется заполнять руками. У существующей спецификации Purpose уже есть, поэтому дельта ее игнорирует: чтобы поменять Purpose живой спецификации, редактируйте openspec/specs/<capability-path>/spec.md напрямую. Здесь <capability-path> - каталог относительно specs/, например user-auth в плоском проекте или identity/user-auth в проекте, организованном по доменам.

Удаление последнего требования: вывод возможности из спецификаций

Если вы удаляете последнее требование, которое есть у возможности, вы выводите ее из состава спецификаций: вместо пустой спецификации архивация удаляет файл openspec/specs/<capability>/spec.md.

Это единственный шаг архивации, который удаляет файл, поэтому его нужно запрашивать явно: добавьте retire_capabilities: true в файл .openspec.yaml изменения, рядом с обязательной секцией schema::

yaml
# openspec/changes/<name>/.openspec.yaml
schema: ...
retire_capabilities: true

Без этого флага архивация прерывается и сообщает об этом.

Так как вывод удаляет файл целиком, он также блокируется, пока в спецификации есть что-либо помимо заголовка, секции ## Purpose и блоков требований - например, секция ## Notes или комментарий под требованием. Сообщение о прерывании называет эти строки: перенесите их в ## Purpose или в требование либо удалите спецификацию вручную. Если спецификация лежит в checkout того, кто запускает архивацию, вывод архивации дополнительно подсказывает команду git checkout, восстанавливающую закоммиченный файл; для отдельных Store выдаются инструкции по восстановлению в рамках checkout.

Правильный размер изменения

Самая частая ошибка автора - не плохо сформулированное требование, а изменение, которое пытается быть тремя изменениями сразу.

У хорошего изменения одна цель, формулируемая одним предложением. «Add a dark-mode toggle». «Rate-limit the login endpoint». «Migrate sessions off cookies». Если для описания изменения нужно много «а также» - это сигнал разделить его.

Признаки того, что изменение слишком велико:

  • рамки proposal читаются как список никак не связанных фич;
  • ревью заняло бы полдня - значит, его никто не сделает;
  • два человека не смогли бы работать над ним, не сталкиваясь друг с другом;
  • половину задач можно было бы выпустить самостоятельно.

Маленькие изменения легче ревьюить, легче собрать за одну сфокусированную сессию и легче понимать полгода спустя, когда от изменения остался только архив. Ничто не мешает запускать несколько изменений параллельно.

Сводка сигналов и действий:

Сигнал Что делать
описание требует много «а также» разделить изменение на несколько
рамки proposal - список несвязанных фич разделить
ревью заняло бы полдня разделить - иначе ревью не состоится
над изменением не работают двое без конфликтов разделить
половина задач выпускается самостоятельно выделить эту половину в отдельное изменение
однострочный фикс опечатки обойтись без трех требований и design-документа

Бывает и обратное: однострочный фикс опечатки не нуждается в трех требованиях и документе дизайна. Соизмеряйте церемонию со ставками.

Как направить агента к хорошему черновику

Поскольку первый черновик делает /opsx:propose, качество результата отслеживает качество того, что вы ему дали. Писать требования руками не нужно - нужно точно прицелить агента:

  • Сформулируйте цель и границу. «Добавь переключатель темной темы, который при первой загрузке следует настройке ОС, - не трогай существующий theme API». Половина «что не делать» важна не меньше половины «что сделать».
  • Назовите случаи, которые вам важны. «Проследи, чтобы появился сценарий для пользователя, который уже выбрал тему вручную». Агент покрывает то, на что вы указываете.
  • Потом редактируйте. Это обычный Markdown. Заострите размытый SHALL, удалите сценарий, который ничего не проверяет, добавьте пропущенный случай - или попросите агента: «требование про таймаут размыто - зафиксируй 30 минут».

Черновик, заострение, повтор. Несколько таких кругов дают спецификацию, которой можно доверять, - в этом и состоит смысл процесса.

Собранный из рекомендаций документации пример запроса, который прицеливает /opsx:propose с первого раза:

text
Добавь переключатель темной темы. При первой загрузке тема следует
настройке ОС. Не трогай существующий theme API.

Проследи, чтобы в сценариях был случай пользователя, который уже
выбрал тему вручную.

Здесь есть обе половины прицела: цель с границей («не трогай theme API») и названный случай, который обязательно нужно покрыть.

Чек-лист автора спецификации

text
- [ ] Каждое требование - одно наблюдаемое поведение с одним SHALL/MUST.
- [ ] В требования не запечены детали реализации.
- [ ] У каждого требования есть хотя бы один сценарий, который реально его проверяет.
- [ ] Важные граничные и ошибочные случаи покрыты сценариями, а не только happy path.
- [ ] Дельты корректно используют ADDED / MODIFIED / REMOVED относительно текущей спецификации.
- [ ] У всего изменения одна цель, формулируемая одним предложением.

Часть 2. Двухминутное ревью плана до кода

Главное обещание OpenSpec - вы и ваш AI согласны, что строить, еще до написания кода. Это согласие имеет смысл, только если вы действительно читаете то, что агент подготовил. Раздел - о тех двух минутах: что открыть, в каком порядке и что искать.

Два момента, когда вы делаете ревью

Их ровно два:

  1. После /opsx:propose (или /opsx:ff), до /opsx:apply - читайте план, пока он еще только текст.
  2. После сборки, командой /opsx:verify - проверяйте, что код сделал то, о чем договорился план.

Первое ревью экономит больше всего - и именно его пропускают. Ниже основное внимание уделено ему.

Порядок чтения: три файла, три вопроса

Изменение - каталог обычного Markdown в openspec/changes/<name>/. Читайте файлы в порядке, который позволяет закончить как можно раньше, если что-то не так:

text
openspec/changes/add-dark-mode/
├── proposal.md      1. цель и рамки    ← если здесь ошибка, дальше не читайте
├── specs/…/spec.md  2. требования      ← сердце ревью
├── design.md        (только для крупных изменений) - технический подход
└── tasks.md         3. план работ

Читать каждую строку не нужно. Нужно ответить на три вопроса - по одному на файл.

Логика чтения - выходить из ревью как можно раньше, как только найдена проблема:

flowchart TD A["proposal.md<br>та ли проблема?"] -->|"нет"| S["Стоп: исправить proposal"] A -->|"да"| B["specs/…/spec.md<br>правильно ли определено «готово»?"] B -->|"нет"| S B -->|"да"| C["tasks.md<br>адекватен ли план работ?"] C -->|"нет"| S C -->|"да"| OK["Ревью пройдено:<br>/opsx:apply"]

Ошибки в первом файле обесценивают чтение остальных: нет смысла проверять требования изменения, которое решает не ту проблему.

proposal.md: та ли это проблема

Откройте proposal.md первым. Он фиксирует «зачем» и «что»: цель, рамки, подход в абзаце-двух.

Как выглядит хорошее: одна ясная цель, рамки, которые вы узнаете, и причина, почему это стоит делать сейчас.

Красные флаги:

  • решается слегка другая проблема, чем та, о которой вы просили;
  • рамки разрослись - вы просили переключатель темы, а proposal заодно трогает auth «раз уж мы здесь»;
  • размытость. «Improve the settings page» - не рамки; «add a dark-mode toggle that respects the OS preference» - рамки.

Вопрос, на который нужно ответить: это совпадает с тем, что я реально просил, и не проползло ли что-то лишнее? Если нет - остановитесь, дальше не читайте, исправьте proposal (как - в части 3).

Дельта-спецификации: правильно ли определено «готово»

Это сердце ревью. Дельта-спецификации в specs/ говорят, что станет истинным, когда изменение выпустится, - в виде требований и сценариев, которые их доказывают:

markdown
## ADDED Requirements

### Requirement: Dark Mode Toggle
The system SHALL let a user switch between light and dark themes.

#### Scenario: Respects the OS preference on first load
- GIVEN a user who has never set a theme
- WHEN they open the app on a device set to dark mode
- THEN the app renders in dark mode

Как выглядит хорошее: одно ясное утверждение SHALL/MUST, которое можно передать тестировщику, и хотя бы один сценарий, чей GIVEN/WHEN/THEN реально проверяет это утверждение.

Красные флаги:

  • Размытое требование. «The system SHALL be fast» нельзя ни построить, ни протестировать. Что такое «fast»?
  • Требование без сценария - или сценарий, который не проверяет требование, под которым сидит.
  • Самая ценная находка - то, чего не хватает. Агент честно записывает то, что вы сказали. Ваша работа - заметить то, что вы забыли сказать. Если вам важнее всего случай с настройкой ОС, а ни один сценарий его не упоминает, - вот тут ревью окупается.

Читайте дельты с вопросом я буду доволен, если система будет делать ровно это - и только это? Здесь еще нет ничего про код, поэтому изменения стоят дешево.

tasks.md: адекватен ли план работ

Откройте tasks.md последним. Это чек-лист реализации, по которому агент будет работать.

Как выглядит хорошее: упорядоченные шаги, каждый сводится к требованию, ничего загадочного.

Красные флаги:

  • задача без соответствующего требования (откуда она взялась?);
  • одна гигантская задача «реализовать фичу», прячущая все реальные решения;
  • задача, трогающая что-то за пределами рамок, которые вы только что одобрили.

Здесь вы не оцениваете трудозатраты и не микроменеджите - вы проверяете, что план соответствует уже принятым требованиям.

Возражать - дешево

Если любой из трех вопросов получил ответ «нет» - скажите об этом. Фаз нет, ничего не заблокировано: исправляете и двигаетесь дальше. Способа два, ровно как в части 3:

  • Отредактировать файл самостоятельно. Это обычный Markdown: поменяйте строку рамок, заострите требование, удалите задачу.
  • Сказать агенту, что не так, и дать переработать: «убери правки auth - вне рамок», «добавь сценарий для пользователя, который уже выбрал тему вручную», «раздели задачу 3 на схему и UI».

Затем перечитайте то, что поменяли, - и так до плана, под которым вы готовы поставить подпись. Это перемещение туда-сюда и есть продукт, работающий как задумано.

Инженерный вывод курса: двухминутное ревью - самая дешевая точка контроля во всем цикле. Ни одна другая практика из модуля не дает сопоставимого соотношения «найденная ошибка / потраченное время»: после /opsx:apply цена той же ошибки вырастает на порядок, потому что исправлять приходится уже код и, возможно, зависимые от него решения.

После кода: /opsx:verify

Когда работа построена, вторым ревью становится /opsx:verify. Команда перечитывает артефакты и код и сообщает о расхождениях по трем измерениям:

Измерение Что проверяет
Completeness все задачи выполнены, все требования реализованы, сценарии покрыты
Correctness реализация соответствует смыслу спецификации, граничные случаи обработаны
Coherence решения из design действительно присутствуют в коде
text
You: /opsx:verify

AI:  Verifying add-dark-mode...

     COMPLETENESS
     ✓ All 8 tasks in tasks.md are checked
     ✓ All requirements in specs have corresponding code
     ⚠ Scenario "Respects the OS preference on first load" has no test coverage

Команда помечает проблемы как CRITICAL, WARNING или SUGGESTION и не блокирует архивацию: она показывает пробелы и оставляет решение вам. В этом разница между «написал ли агент код» и «построил ли он то, о чем мы договорились».

/opsx:verify входит в расширенный профиль команд. Если команды нет, включите профиль через openspec config profile (затем openspec update) - или просто перечитайте изменение и diff самостоятельно. Подробности команды - в справочнике 15.5.

Как читать вывод: статус ✓ подтверждает измерение, ⚠ указывает на пробел - в примере выше сценарий «Respects the OS preference on first load» реализован, но не покрыт тестом. Уровень сообщения подсказывает приоритет, а решение, что исправлять, остается за вами.

Ревью по размеру изменения

Не каждое изменение заслуживает полного прохода. Однофайловый фикс опечатки заслуживает двадцатисекундного взгляда. Изменение, которое трогает auth, платежи или невосстановимые данные, заслуживает каждого вопроса из этого раздела. Смысл никогда не был в церемонии - в том, чтобы тратить внимание там, где ошибка обойдется дорого, и пробегать взглядом там, где нет.

Двухминутный чек-лист

text
- [ ] Цель proposal совпадает с тем, что я просил.
- [ ] В рамки не проползло ничего лишнего.
- [ ] Каждое требование достаточно конкретно, чтобы его тестировать.
- [ ] У каждого требования есть сценарий, который реально его проверяет.
- [ ] Самый важный для меня случай покрыт.
- [ ] Задачи сводятся к требованиям; нет ничего загадочного и вне рамок.
- [ ] Меня устроит, если агент построит ровно это и ничего больше.

Если все семь пунктов проходят - запускайте /opsx:apply с уверенностью. Если какой-то не проходит - это не откат назад, это две минуты, которые сделали свою работу.

Часть 3. Редактирование изменения

Каждый артефакт изменения - это просто Markdown-файл, который можно редактировать в любой момент. Нет заблокированной «фазы планирования», нет ворот одобрения, нет специального режима правки. Хотите поменять proposal после начала сборки? Откройте proposal.md и поменяйте. Поняли посреди реализации, что design неверен? Исправьте design.md и продолжайте. Это весь ответ - и так задумано.

Раздел - для момента, когда вы думаете: «стоп, а можно ли вернуться и поменять то, что уже решено?» Можно. Вот как, для каждого типового случая.

Сводка типовых вопросов, на которые отвечает эта часть:

Вопрос Короткий ответ Подраздел
Как обновить proposal или specs после старта работы? просто обновите - то же изменение, уточненное ниже
Как вернуться к ревью после начала реализации? никак - вы из него и не выходили ниже
Отредактировал код руками. Как помирить с OpenSpec? синхронизируйте в сторону истины до архивации ниже
Proposal промахнулся. Что делать? три хода: итерировать, explore, начать заново ниже
Обновлять изменение или заводить новое? уточнение той же работы - обновлять; новая цель - новое ниже

Два способа отредактировать что угодно

Способа всегда два:

  1. Отредактировать файл напрямую. Артефакты - обычный Markdown в openspec/changes/<name>/. Откройте proposal.md, design.md, tasks.md или дельта-спецификацию в specs/ в редакторе и измените. Больше ничего не требуется.
  2. Попросить агента переработать. В чате просто скажите, что нужно: «обнови proposal - убери идею с кэшированием и добавь раздел про rate limit» или «в design должна быть очередь, а не polling». Агент редактирует артефакт за вас, используя остальное изменение как контекст.

Выбирайте по ситуации. Малая правка формулировки - редактируйте файл. Существенное переосмысление - пусть перерабатывает агент с полным контекстом.

Оба способа дают одинаковый результат: агент работает с текущим содержимым файлов, поэтому неважно, кто именно внес правку - вы в редакторе или агент по вашей просьбе.

Как обновить proposal или specs, когда работа уже началась

Просто обновите. То же изменение, уточненное.

Если вы используете расширенный набор команд, естественный поток такой: отредактируйте артефакт, затем запустите /opsx:continue, чтобы продолжить с нового состояния, или /opsx:apply, чтобы продолжить реализацию по обновленному плану. Если вы на базовом наборе core - отредактируйте артефакт и запустите /opsx:apply: команда читает текущие файлы и строит по тому, что в них написано сейчас.

Ментальная модель: артефакты - живой план, а не подписанный контракт. Агент всегда работает от их текущего содержимого, поэтому редактирование и есть управление работой:

text
Вы:  хочу поменять подход в этом изменении.

Вы:  [правите design.md сами или просите агента:]
      Update design.md to use a background job instead of a
      synchronous call.

AI:  Updated design.md. The task list still fits; want me to
     continue applying?

Вы:  /opsx:apply

Отсюда ответ на частый вопрос: отдельной команды «обновить proposal» нет, потому что она не нужна. Файл - источник истины, и его редактирование (руками или через агента) и есть обновление.

Как вернуться к ревью после реализации

«Возвращаться» не нужно - вы и не уходили. Workflow текуч: ревью, правки и реализация - не последовательные фазы, из которых нельзя выбраться.

Конкретно, после некоторого объема работы /opsx:apply:

  • хотите заново взглянуть на план - откройте артефакты и прочитайте их или выполните openspec show <change> в терминале для сводного просмотра;
  • нашли, что поправить, - отредактируйте артефакт (или попросите агента) и продолжайте;
  • хотите структурной проверки, что код соответствует плану, - запустите /opsx:verify (расширенная команда): она сообщает о полноте, корректности и согласованности, ничего не блокируя.

«Фазы ревью», в которую надо возвращаться, нет, потому что ревью - это то, что можно делать в любой момент, включая время после реализации.

Ручные правки кода: reconciliation со спецификацией

Это происходит постоянно, и это нормально. Вы что-то подправили в редакторе - и теперь код и артефакты расходятся. Верните их в синхрон в ту сторону, которая отражает истину:

flowchart TD D{"Код и спецификация<br>разошлись"} D -->|"код теперь верен,<br>спецификация устарела"| U["Обновить дельту и tasks<br>под реально поставленное поведение"] D -->|"спецификация верна,<br>код ушел в сторону"| F["Продолжать сборку,<br>пока код не совпадет со spec"] D -->|"неясно, где именно"| V["/opsx:verify:<br>список расхождений"] V --> D U --> AR["Архивация: specs стали<br>протоколом истины"] F --> AR
  • Код теперь верен, спецификация устарела. Обновите дельта-спецификацию (и задачи, если важно), чтобы описывать поведение, которое вы реально получили. Спецификация должна совпадать с реальностью до архивации, потому что архивация вливает ее в источник истины.
  • Спецификация верна, код ушел в сторону. Продолжайте строить или исправлять, пока код не совпадет со спецификацией.

Быстрый способ найти расхождения - /opsx:verify: команда читает артефакты и код и показывает, где они расходятся. Отнеситесь к ее выводу как к списку задач для синхронизации - и архивируйте, когда они согласятся.

Принцип: в момент архивации спецификации становятся протоколом истины. Поэтому до архивации сделайте спецификации честными относительно того, что делает код. Ручные правки приветствуются - просто не позволяйте им тихо рассинхронизировать спецификацию.

Инженерный вывод курса: правило «спецификация должна быть честной к моменту архивации» переносится на любой Spec-Driven инструмент из урока 2.10. Момент слияния дельты в living spec - последняя дешевая точка, где можно остановить расхождение плана и реальности; после архивации оно уже часть «истории».

Три хода при неудачном proposal

Если сгенерированный proposal не попал в цель, есть три рабочих хода:

  • Итерировать на месте. Скажите агенту, что не так («рамки слишком широкие - убери админ-функции»), и дайте переработать. Дешевле всего и обычно правильно.
  • Сначала explore, потом новый proposal. Если проблема в том, что сама идея еще не ясна, отступите к /opsx:explore, продумайте ее - и пусть более точный proposal выйдет оттуда.
  • Начать заново. Если цель фундаментально изменилась, новое изменение может быть яснее, чем залатанное старое.

Обновлять существующее или начинать новое изменение

Коротко: обновляйте, когда это та же работа в уточненной форме; начинайте новое, когда цель фундаментально изменилась или рамки взорвались в другую работу.

  • Та же цель, но подход лучше? Обновляйте.
  • Рамки сужаются (выпустить MVP сейчас, остальное потом)? Обновите, заархивируйте, затем новое изменение для второй фазы.
  • Сама проблема изменилась («добавить темную тему» превратилось в «построить полноценную систему тем»)? Новое изменение.

Полный флоучарт и разобранные примеры - в документации Workflows и более глубоко в OPSX; в модуле эта логика разбирается в уроке 15.8.

tasks.md - живой чек-лист

tasks.md - живой чек-лист, а не замороженный план. По ходу реализации можно добавлять обнаруженные задачи, удалять оказавшиеся ненужными, менять порядок. Агент отмечает пункты по мере выполнения во время /opsx:apply и возобновляет работу с первого непроверенного пункта, если вы вернетесь позже. Редактировать список посреди работы - ожидаемое поведение.

Практика

  1. В тестовом проекте из урока 15.9 создайте изменение с одной целью, формулируемой одним предложением: например, /opsx:propose rate-limit-login.
  2. Прочитайте артефакты в порядке proposal → specs → tasks и ответьте на три вопроса ревью: та ли проблема, правильно ли определено «готово», адекватен ли план работ.
  3. Прогоните двухминутный чек-лист. Найдите хотя бы один «красный флаг» - проще всего обнаруживается сценарий, не покрывающий самый важный вам случай.
  4. Исправьте один артефакт вручную в редакторе, другой - попросив агента переформулировать. Сравните, какой способ оказался удобнее для каждого случая.
  5. Проверьте выбор типа дельты: откройте текущую спецификацию затронутой возможности и убедитесь, что каждое требование помечено корректным ADDED / MODIFIED / REMOVED.
  6. После /opsx:apply запустите /opsx:verify (или перечитайте изменение и diff самостоятельно) и решите для каждого предупреждения: исправить код, исправить спецификацию или принять как есть.

Краткое резюме

Три документа документации - про одно: спецификация приносит пользу, когда ее пишут сильно, читают внимательно и правят без церемоний.

  • Требование - одно наблюдаемое поведение с одним SHALL/MUST; сценарий - конкретный GIVEN/WHEN/THEN, который его реально проверяет; детали реализации остаются в design.md и коде.
  • Дельта выбирается между ADDED / MODIFIED / REMOVED по отношению к текущей спецификации; новая возможность открывается секцией ## Purpose; удаление последнего требования требует retire_capabilities: true в .openspec.yaml.
  • Хорошее изменение имеет одну цель, формулируемую одним предложением; «а также» - сигнал делить.
  • Ревью плана - два минуты по порядку proposal → specs → tasks, три вопроса, семь пунктов чек-листа; после кода - /opsx:verify по измерениям completeness, correctness, coherence.
  • Артефакты - живой Markdown без фаз и блокировок: правьте руками или через агента; ручные правки кода синхронизируйте со спецификацией до архивации.

Вопросы для самопроверки

  1. Чем требование отличается от сценария и почему смешение поведения с реализацией делает требование непроверяемым?
  2. Что означают ключевые слова RFC 2119 MUST/SHALL, SHOULD и MAY - и когда уместно ослабить SHALL до SHOULD?
  3. Чем дельта ADDED отличается от MODIFIED, и к чему приводит каждая из двух ошибок выбора?
  4. Что произойдет при архивации изменения, удаляющего последнее требование возможности, если в .openspec.yaml нет retire_capabilities: true? А если в спецификации осталась секция ## Notes?
  5. В каком порядке читают артефакты drafted-изменения и почему именно в таком?
  6. Код отредактирован вручную и разошелся со спецификацией: в какую из двух сторон выполняется reconciliation и какова роль /opsx:verify в нем?

Что дальше

Урок 15.11 - OpenSpec в существующем проекте (brownfield): как внедрять спецификации на большом живом codebase, не описывая все сразу, - от первого маленького изменения к постепенно выросшей living spec.

Источники

Обновлено 03.10.2026