Харнесс-инженерия против Spec-Driven Development: зачем нужно и то, и другое

· 7 мин чтения
harness-engineering spec-driven ai-agents ci-cd verification
Харнесс-инженерия против Spec-Driven Development: зачем нужно и то, и другое

Spec-driven development отвечает на вопрос «что именно должно сделать это изменение». Харнесс-инженерия отвечает на другой вопрос: «как сделать так, чтобы любое изменение можно было дёшево проверить». Первое без второго превращается в документ, который никто не проверяет. Второе без первого — в зелёный конвейер, нацеленный не туда. Команды, которые всерьёз пишут код с ИИ-агентами, нуждаются в обоих подходах: спецификация задаёт намерение, а харнесс принуждает к нему и проверяет результат.

Что такое харнесс-инженерия

Харнесс — это всё в ИИ-агенте, кроме модели: инструменты, контекст, ограничения и проверки. Биргитта Бёкелер из martinfowler.com даёт короткое определение: «всё в ИИ-агенте, кроме самой модели». Отсюда формула: агент = модель + харнесс.

Показательный пример — публикация OpenAI в феврале 2026 года. Команда Райана Лопополо за пять месяцев выпустила внутренний продукт примерно на миллион строк кода и полторы тысячи смерженных pull request — без единой строки, написанной руками. Формула команды умещается в четыре слова: люди рулят, агенты исполняют. Из отчёта выделяются четыре практики:

  • Репозиторий — единственный источник правды (system of record). Всё, что агент не может прочитать во время работы, для него не существует.
  • AGENTS.md — оглавление примерно на 100 строк, а не энциклопедия.
  • Инварианты — правила, которые нельзя нарушать, — проверяются механически, а сообщения линтеров написаны как инструкции по исправлению.
  • Беспорядок в коде чистят непрерывно: фоновые PR на рефакторинг, «как сборка мусора».

Anthropic в статьях ноября 2025 и марта 2026 года разбирает харнесс для долгоживущих агентов: агент-инициализатор готовит окружение и пишет init.sh, а в сложных сценариях работа делится между планировщиком, генератором и оценщиком. Оценщик сверяет результат с заранее согласованными критериями.

Четыре слоя вокруг модели

Адди Османи (июнь 2026) выстраивает практики работы с агентами в четыре вложенных слоя — каждый включает предыдущий:

Слой Что вы проектируете Типичный артефакт
Prompt engineering одну инструкцию на один запрос хорошо структурированный промпт
Context engineering какие токены попадают в окно правила поиска, сжатие истории, подобранные примеры
Харнесс-инженерия инструменты, ограничения и проверки вокруг агента AGENTS.md, линтеры, структурные тесты, CI-гейты
Loop engineering что агент делает дальше и когда останавливается триггеры, верификаторы, правила остановки, лимиты повторов

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

Два подхода, два разных вопроса

Spec-driven development Харнесс-инженерия
Вопрос Что должно сделать это изменение? Как сделать любое изменение проверяемым?
Масштаб одно изменение или фича весь репозиторий, на всю его жизнь
Артефакты spec.md, tasks.md, критерии приёмки, evidence.md AGENTS.md, документация, линтеры, структурные тесты, тест-харнесс, CI
Когда меняется с каждой новой фичей когда одна и та же ошибка повторилась дважды
Какой риск убирает агент додумал пропущенное требование вывод агента тихо ухудшает кодовую базу
Что будет без него команда спорит о задуманном поведении на ревью команда согласна насчёт поведения, но не может дёшево это доказать

Где подходы встречаются

Бёкелер делит компоненты харнесса на два типа:

  • Гайды работают «до»: предугадывают поведение агента и направляют его до того, как он начнёт действовать.
  • Сенсоры работают «после»: наблюдают за результатом и помогают агенту исправиться самому.

Каждый тип бывает вычислительным — тесты, линтеры, проверка типов — или рассуждающим, когда оценкой занимается другая модель, например ИИ-ревью кода. Спецификация в этой схеме — гайд. Причём единственная часть харнесса, которая меняется от фичи к фиче: всё остальное настраивается один раз и работает долго.

Между разделами спецификации и контролами харнесса есть прямое соответствие:

Раздел спецификации Контроль в харнессе Тип
Контекст, цель, non-goals ссылка из AGENTS.md, чтобы агент прочитал спеку первым гайд
Allowed files CI падает, если diff трогает что-то ещё вычислительный сенсор
Критерии AC-1…AC-n минимум один тест упоминает каждый критерий, иначе CI падает вычислительный сенсор
Edge cases фикстуры и фабрики данных, воспроизводящие их тест-харнесс
API-контракт контрактные тесты из OpenAPI-документа вычислительный сенсор
Evidence раздел в шаблоне PR с именами тестов и логами ИИ-ревью
Rollback фича-флаг существует и по умолчанию выключен вычислительный сенсор

Пример: повторная попытка возврата денег

Спека на эндпоинт возврата с повторной попыткой:

  • AC-1: при таймауте шлюза возврат повторяется один раз с тем же ключом идемпотентности.
  • AC-2: при втором таймауте возврат остаётся в статусе «в ожидании», дубликата refund_id нет.
  • AC-3: каждая попытка пишет событие в аудит-лог.
  • Allowed files: src/billing/refund-worker.ts, tests/refund-worker.test.ts, specs/active/refund-retry/evidence.md.

Без харнесса агент пишет правдоподобный цикл повторов и тест, в котором мок шлюза со второй попытки отвечает успехом. AC-2 не проверяется никогда — но тест зелёный. Заодно агент добавляет хелпер в src/billing/ledger.ts, потому что так «аккуратнее». Все три ошибки находит человек на ревью — поздно и дорого.

С харнессом три сенсора срабатывают до ревью. Гейт по Allowed files ловит изменение ledger.ts — и сборка падает. Проверка критериев сообщает: ни один тест не упоминает AC-2. А мок шлюза живёт в тест-харнессе, а не выдумывается под каждый тест, — в нём есть готовое состояние «дважды таймаут», и недостающий тест стоит агенту одну строку. Спека задала намерение, а харнесс поймал все упрощения агента — пока их было дёшево исправить.

Спек-гейт: самый дешёвый датчик

Минимальный сенсор — скрипт scripts/spec-gate.sh <change-name> [base-ref]. Он падает в двух случаях: diff вышел за пределы списка Allowed files или какой-то критерий не покрыт тестом. Скрипт совместим с bash 3.2 — версией по умолчанию на macOS:

#!/usr/bin/env bash
set -euo pipefail

change="$1"
base="${2:-origin/main}"
spec="specs/active/$change/spec.md"
status=0

allowed=$(sed -n '/^## Allowed files/,/^## /p' "$spec" | grep '^- ' || true)

for file in $(git diff --name-only "$base"...HEAD); do
  if ! printf '%s\n' "$allowed" | grep -qx -- "$file"; then
    echo "out of scope: $file"
    status=1
  fi
done

for ac in $(grep -o 'AC-[0-9]*' "$spec" | sort -u); do
  if ! grep -rqw "$ac" tests/; then
    echo "no test mentions $ac"
    status=1
  fi
done

exit $status

Деталь, на которой автор делает акцент: проверка критериев использует grep -w — поиск по целому слову. Без него тест, упоминающий AC-10, закрывал бы и AC-1: подстрока AC-1 входит в AC-10.

В CI скрипт подключается одним шагом:

name: spec-gate
on: pull_request
jobs:
  gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - run: scripts/spec-gate.sh "$GITHUB_HEAD_REF" "origin/$GITHUB_BASE_REF"

Имя ветки служит именем папки со спекой, а fetch-depth: 0 даёт полную историю git для сравнения с базовой веткой.

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

Что происходит без второй половины

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

Харнесс без спецификации — зелёный конвейер, нацеленный не туда. Anthropic описала ловушку так: «Когда агентов просят оценить их собственную работу, они обычно уверенно её хвалят». Лекарство — заранее согласованные критерии. То есть спецификация, как её ни называй.

И оговорка OpenAI: результаты эксперимента нельзя переносить на другие команды без сопоставимых вложений. Харнесс строят, а не устанавливают.

Стартовый харнесс за неделю

С чего начать — примерно неделя работы. Порядок по убыванию отдачи:

  1. Сделайте AGENTS.md картой: коротко, со ссылками на спеки, архитектурные заметки и команды.
  2. В каждую спеку добавьте нумерованные критерии приёмки и список разрешённых файлов.
  3. Подключите спек-гейт к CI: он почти ничего не стоит и ловит больше всего.
  4. Соберите один настоящий слой тест-харнесса: фикстуры, мок-сервер или поднятие окружения — в зависимости от того, на чём спотыкаются ваши агенты.
  5. Добавьте в шаблон PR раздел с доказательствами: имена тестов по каждому критерию, логи, скриншоты. Ревьюеру будет что читать.
  6. Превращайте повторяющиеся ошибки в новые контролы: ошибка повторилась — добавьте гайд (строку в AGENTS.md, шаблон спеки) или сенсор (линтер, тест).

Спецификация говорит агенту, что сделать. Харнесс проверяет, что сделано именно это. По отдельности каждая дисциплина оставляет дыру ровно там, где заканчивается другая.

Источник: https://spec-coding.dev/blog/harness-engineering-vs-spec-driven-development