Skip to content
Все посты /

Контракт — это контекст: как Signum делает верификацию AI-кода принципиальной

Почему прогнать AI-код через ещё больше AI-ревьюеров не решает проблему надёжности — и что меняет подход contract-first.

#context-engineering #claude-code #agents #verification #contract-first

Можно прогнать AI-diff через три модели и всё равно не иметь точки истины. Они скажут что выглядит “разумно”, а не что корректно.

Модель отказа не в “плохом коде”. Она в нефальсифицируемом намерении: требование так и не стало чем-то, что можно запустить. Вы одобрили реализацию, удовлетворяющую вашим допущениям. Граничные случаи, которые вы не потрудились специфицировать, не были пойманы — потому что ловить было не против чего. Два месяца спустя приходит баг-репорт.

Это проблема контекстной инженерии.

Недостающий слой контекста

У каждого процесса верификации нужно две вещи: артефакт, который проверяется, и стандарт, относительно которого он проверяется. Современное код-ревью сильно с первым и слабо со вторым. “Стандарт” живёт в голове ревьюера — восстановленный из описания задачи, комментариев и окружающего кода. Неявный, неполный, ни с кем не разделённый.

Контекстная инженерия — это превращение неявного контекста в явный. Для верификации это означает: стандарт должен существовать до начала реализации, а не после. Контракт — это контекст. Без него всякое ревью — это интерпретация.

Signum: контракт как точка истины

Signum — плагин для Claude Code, реализующий четырёхфазный пайплайн:

CONTRACT → EXECUTE → AUDIT → PACK

CONTRACT идёт первым. Вы описываете задачу на естественном языке. Агент-контрактор (Claude Sonnet) формализует её в contract.json:

{
  "goal": "Добавить rate limiting на POST /api/tokens — макс. 5 запросов в минуту на IP",
  "acceptanceCriteria": [
    {
      "id": "AC1",
      "description": "Запросы сверх лимита возвращают 429 с заголовком Retry-After",
      "verify": "pytest tests/test_rate_limit.py -k test_429_response",
      "holdout": false
    },
    {
      "id": "AC2",
      "description": "Счётчик rate limit сбрасывается после истечения окна",
      "verify": "pytest tests/test_rate_limit.py -k test_window_reset",
      "holdout": true
    }
  ],
  "inScope": ["src/api/tokens.py", "tests/test_rate_limit.py"],
  "riskLevel": "medium"
}

Спецификация оценивается по шкале A–F по шести измерениям (тестируемость, покрытие негативных сценариев, ясность, область, полнота, граничные случаи). Оценка D — жёсткая остановка: пайплайн не продолжается, пока спецификация не станет верифицируемой.

EXECUTE: Агент-инженер получает contract-engineer.json — контракт с физически удалёнными критериями holdout: true. Он реализует против видимой спецификации. Оптимизировать под то, чего не видишь, невозможно.

AUDIT: Механик (детерминированный, без LLM) запускает lint, typecheck и тесты относительно pre-реализационного baseline. Затем Claude, Codex и Gemini независимо проверяют diff параллельно. Holdout-критерии — AC2 в примере выше — запускаются против готового результата. Если инженер забыл сбросить счётчик после истечения окна, это поймается здесь, автоматически, против критерия, который он никогда не видел.

PACK: proofpack.json — SHA-256 контракта, временная метка одобрения, базовый коммит, diff, результаты аудита. CI строит гейты на нём.

Что блокирует Signum

До начала реализации Signum отклоняет:

  • Критерии приёмки без команды verify (нельзя проверить = не критерий)
  • Размытую область (“измени auth-модуль” без конкретных файлов)
  • Рискованные допущения, выявленные внешними валидаторами (Codex + Gemini проверяют спецификацию на пробелы)
  • Спецификации с оценкой ниже D — недостаточные граничные случаи, покрытие негативных сценариев, ясность

После реализации AUTO_BLOCK при:

  • Нарушениях политики (слишком много изменённых файлов, запрещённые bash-паттерны в diff)
  • Регрессиях инвариантов репозитория (если pytest -q проходил до — должен проходить после)
  • Провале holdout-сценариев

Инварианты на уровне репозитория: постоянный контракт

Контракты уровня задачи покрывают то, что вы строите сейчас. repo-contract.json — то, что должно выполняться всегда:

{
  "invariants": [
    { "id": "I-1", "description": "All tests pass", "verify": "pytest -q", "severity": "critical" },
    { "id": "I-2", "description": "No type errors", "verify": "mypy src/", "severity": "critical" }
  ],
  "owner": "human"
}

Signum фиксирует baseline до EXECUTE, перезапускает после. Любая регрессия — AUTO_BLOCK, вне зависимости от результатов уровня задачи. Поле "owner": "human" объявляет этот файл человеческим артефактом. AI enforces; человек определяет.

Цепочка аудита

При одобрении пользователем Signum хэширует contract.json (SHA-256) и фиксирует временную метку. До запуска инженера записывается базовый коммит. Итоговый proofpack связывает: одобренный контракт → базовый коммит → diff реализации → результаты аудита. Нельзя задним числом заменить контракт и заявить, что proofpack был построен против него.

Это важно по мере того, как AI-сгенерированный код всё чаще требует провенанса. Не “AI написал это” — “AI реализовал это против этого контракта, валидированного до реализации, с этими результатами аудита.”

Установка

# Добавить маркетплейс (один раз)
claude plugin marketplace add heurema/emporium

# Установить Signum
claude plugin install signum@emporium

# Опционально: внешние CLI для мультимодельного аудита
# https://github.com/openai/codex
# https://github.com/google-gemini/gemini-cli

Затем:

/signum "добавить rate limiting на API endpoint"

Signum оценивает спецификацию, показывает контракт на одобрение, запускает инженера с удалёнными holdouts, проводит аудит с нескольких сторон и создаёт proofpack.json.

Статус

Работает сейчас: четырёхфазный пайплайн, гейт качества спецификации, holdout-сценарии, инварианты репозитория, цепочка аудита, proofpack.

Требует: Claude Code v2.1+, git, jq, python3. Мультимодельный аудит дополнительно требует Codex CLI и Gemini CLI — Signum деградирует корректно при отсутствии любого из них.

В процессе изменений: схемы артефактов (proofpack, contract) будут меняться. Суждение контрактора о качестве holdout улучшается с использованием.

Мы запускаем Signum на собственной разработке Signum. v3 — первая версия, на которую мы готовы ставить в своих проектах.

Обратная связь

Signum молодой и активно разрабатывается. Если он блокирует некорректно, упускает граничный случай или оценка спецификации кажется неправильной — можно сообщить прямо из Claude Code, без переключения контекста.

Установите Reporter:

claude plugin install reporter@emporium

Затем: /report bug или /report feature или /report question

Reporter автоматически определяет, что вы работаете с продуктом heurema, прикрепляет контекст среды (ОС, оболочка, версия Claude Code), показывает предпросмотр перед отправкой и падает обратно на буфер обмена, если gh недоступен.

Ссылки