Appearance
Проверка результата
Что здесь строим
Verification - это не список команд, которые хорошо бы запускать. Это договор между человеком, harness и агентом: по каким внешним сигналам мы решаем, что работа действительно готова.
В этой главе цель простая: собрать первый quality gate для agent run. Он должен делать три вещи:
- Ловить очевидные ошибки без участия reviewer.
- Давать агенту понятный feedback для retry.
- Останавливать run, когда дальше нужен человек.
С чего начать
Не начинайте с большого набора checks. Начните с одного сценария, который прямо следует из spec.
В lab-цепочке это ALGI pain diary:
text
examples/algi-lite/specs/pain-diary.bdd.md
examples/harness-labs/tasks/algi-01-pain-diary.jsonВ spec есть правило: pain score должен быть от 0 до 10, summary не должен раскрывать прямые identifiers, текст не должен выглядеть как medical advice. Поэтому первый verification слой - unit tests на эти свойства.
Три слоя verification
Для agent run полезно проверять не только финальный outcome.
| Слой | Вопрос | Лучший evidence |
|---|---|---|
| Outcome | Был ли результат реально достигнут? | Tests, database/file state, API response, rendered UI. |
| Process | Был ли путь допустимым? | Policy decisions, tool sequence, approvals, permissions. |
| Quality | Хорошо ли сделан результат в смысле продукта и команды? | Rubric, review notes, screenshots, domain evaluator. |
Пример: clinician summary может проходить unit tests, но нарушить process, если agent прочитал запрещённый file с patient identifiers. Или пройти outcome/process, но получить needs_review, если wording выглядит как medical advice. Поэтому done должен зависеть от комбинации checks, а не от одного зелёного сигнала.
В каком порядке добавлять проверки
Добавляйте verification слоями. Не все слои одинаково важны на старте.
1. Behavior test
Первый слой проверяет behavior из spec.
Пример из lab:
python
def test_invalid_score_is_rejected(self):
with self.assertRaisesRegex(ValidationError, "between 0 and 10"):
validate_pain_entry(13)Это хороший первый check, потому что он связан с product rule, а не с внутренним устройством кода.
Плохой первый check:
python
self.assertEqual(type(entry).__name__, "PainEntry")Такой тест легко ломается при безопасном refactor и почти ничего не говорит о product behavior.
2. Regression test для риска
Второй слой фиксирует риск, который нельзя пропустить.
Для ALGI это privacy:
python
rendered = repr(summary)
self.assertNotIn("@", rendered)
self.assertNotIn("+1", rendered)Да, это грубая проверка. Но для первого harness она полезна: если agent случайно протащит email или телефон в clinician summary, run упадёт автоматически.
Позже такой check можно заменить на более точный privacy evaluator.
3. Static checks
Когда behavior tests уже есть, добавляйте дешёвые static checks:
- format;
- lint;
- typecheck;
- build или compile check.
Static checks важны, но они не заменяют behavior tests. Код может быть идеально отформатирован и всё равно нарушать spec.
В Python seed можно начать с:
bash
python3 -m py_compile algi/domain.py
python3 -m unittest discover -s tests4. Domain evaluator
Evaluator нужен там, где обычный assert плохо выражает качество:
- summary не должен звучать как diagnosis;
- ответ должен быть понятен пациенту;
- generated report должен сохранять clinical caution;
- UI copy не должен обещать лечение.
Минимальный evaluator может быть простым checklist, который возвращает pass/fail. Более зрелый evaluator может быть отдельным script или LLM-as-judge, но его тоже надо versioned, логировать и проверять на regressions.
5. Review gate
Некоторые изменения нельзя принять только по tests:
- privacy-sensitive behavior;
- auth/security;
- migrations;
- production operations;
- medical/domain wording;
- изменения policy или permissions.
Для таких задач result должен быть needs_review, даже если tests зелёные.
Как это подключается к harness
Task contract должен содержать checks:
json
{
"checks": [
{
"name": "unit tests",
"command": ["python3", "-m", "unittest", "discover", "-s", "tests"]
}
]
}Harness делает не просто subprocess.run. Он должен:
- Проверить command через policy.
- Записать
check_started. - Запустить command в workspace.
- Записать
check_finishedс exit code и output. - Принять result classification.
В harness-labs это появляется в v02, а в v03 дополняется policy gate.
Как выбирать outcome
| Outcome | Когда ставить | Что делать дальше |
|---|---|---|
done | Все required checks прошли, policy exceptions нет, review gate не нужен. | Передать в обычный review или merge flow. |
retry | Ошибка понятна, feedback машинно читаемый, retry budget не исчерпан. | Вернуть agent конкретный failing check и ограничить scope. |
needs_review | Checks зелёные, но остаётся product/security/architecture риск. | Передать человеку spec, diff, run summary и risk summary. |
blocked | Нужен секрет, доступ, решение по scope, external system или approval. | Остановить run и запросить решение. |
failed | Run нарушил constraints, испортил unrelated surface или не приблизился к решению. | Не retry автоматически; сначала разобрать причину. |
Частая ошибка: retry без нового feedback
Если agent получил тот же prompt и тот же context после failed check, это не engineering loop, а повтор ставки. Retry имеет смысл только если harness добавляет новую информацию:
- exact failing test;
- stderr/stdout summary;
- affected file;
- violated acceptance criterion;
- ограничение "не трогать unrelated files";
- stop condition.
Что сделать руками
- Запустите цепочку из Labs до ALGI pain diary.
- Откройте
/tmp/algi-ch03/tests/test_domain.py. - Найдите tests, которые соответствуют BDD scenarios.
- Добавьте в task ещё один check, например
python3 -m py_compile algi/domain.py. - Запустите harness снова.
- Откройте JSONL log и найдите
check_started,check_finished,result_classified.
Минимальный результат главы: у вас есть не просто тесты в проекте, а harness-level quality gate, который влияет на result classification.
На что не соглашаться
- Не начинать с десяти checks сразу.
- Не принимать self-report агента как доказательство.
- Не смешивать refactor и bug fix в одном run.
- Не делать retry без нового feedback.
- Не прятать human review за зелёными tests, если риск находится вне test coverage.