Skip to content

Разработка от spec

Когда команда отдаёт задачу агенту без spec, она фактически просит его угадать продуктовую логику. Иногда это срабатывает на мелких fixes. На доменной фиче почти всегда всплывает вопрос: агент написал код, но тот ли behavior нам был нужен?

Spec нужен не для бюрократии. Он нужен, чтобы до генерации кода договориться о поведении, ограничениях и проверках. Тогда агент работает не «по ощущению», а по версии истины, которую можно ревьюить, тестировать и переиспользовать.

Рабочая цепочка выглядит так:

text
spec -> task contract -> backend output -> checks -> evidence

В нашем учебном продукте первый spec лежит здесь:

text
examples/algi-lite/specs/pain-diary.bdd.md

Что зафиксировать до кода

Хороший spec отвечает на пять вопросов.

ВопросЧто записать
Какое поведение нужно?Пользовательский или системный результат, а не список файлов.
Где границы?Что входит в scope и что явно не трогаем.
Какие доменные правила нельзя нарушить?Privacy, safety, UX wording, compliance, совместимость.
Как выглядят данные?Поля, типы, обязательные значения, ошибки.
Чем докажем готовность?Tests, evaluator, screenshots, logs, review gate.

Если хотя бы один ответ остаётся устным, агенту придётся достраивать его сам. Это плохая сделка: модель может угадать красиво, но не обязана угадать верно.

Почему здесь удобен BDD

BDD/Gherkin дисциплинирует формулировки. Вместо «сделай нормальную валидацию» появляется сценарий:

gherkin
Scenario: invalid pain score
  Given a patient reports pain score 13
  When the entry is validated
  Then validation fails
  And the error explains that pain score must be between 0 and 10

Такой текст понятен product/domain человеку, reviewer'у и harness. Его можно превратить в тест без длинного обсуждения в чате.

Как scenario становится проверкой

В lab-цепочке сценарии из examples/algi-lite/specs/pain-diary.bdd.md превращаются в реальные tests.

СценарийТестЧто проверяет
valid pain entrytest_valid_entry_is_normalizedscore принят, note нормализована
invalid pain scoretest_invalid_score_is_rejectedValidationError с понятным текстом
privacy-safe clinician summarytest_clinician_summary_is_privacy_safeагрегаты есть, identifiers и medical claims не попали в output

Пример проверки из теста:

python
def test_invalid_score_is_rejected(self):
    with self.assertRaisesRegex(ValidationError, "between 0 and 10"):
        validate_pain_entry(13)

А доменное правило про privacy становится не пожеланием в Markdown, а исполняемой проверкой:

python
summary = clinician_summary(entries)
rendered = repr(summary)

self.assertIn("not medical advice", summary["disclaimer"])
self.assertNotIn("@", rendered)
self.assertNotIn("+1", rendered)

Это и есть смысл разработки от spec: важное правило нельзя нарушить незаметно на следующем run.

Как ревьюить spec

Ревью spec должно происходить до запуска agent backend. Это дешевле, чем спорить о сгенерированном diff.

Проверьте:

  • behavior описан через наблюдаемый результат;
  • scope достаточно мал для одного bounded run;
  • non-goals названы явно;
  • есть negative и edge scenarios;
  • privacy/security constraints вынесены в отдельный блок;
  • testing plan реалистичен;
  • новый инженер поймёт spec без устной экскурсии.

Что сделать руками

  1. Откройте examples/algi-lite/specs/pain-diary.bdd.md.
  2. Пройдитесь по чеклисту ревью spec.
  3. Запустите практическую цепочку из Labs.
  4. Сравните BDD scenarios с tests, которые появляются после запуска harness.

К концу главы у вас должен быть не «документ для агента», а versioned source of truth для маленького product behavior.

На что не соглашаться

  • Запускать coding agent до review spec.
  • Описывать структуру кода вместо behavior.
  • Прятать privacy and safety constraints в комментарии к задаче.
  • Делать только happy path.
  • Использовать spec как одноразовый prompt, который никто больше не увидит.

Agentic Engineering: Context Engineering + Harness Engineering