Перейти к тексту

Проверка результата ​

После первой задачи ALGI runner сообщает done, а три теста проходят. Один из них называется test_clinician_summary_is_privacy_safe. Посмотрим, что он проверяет, прежде чем принимать название теста за свойство продукта.

Прочитайте входные данные теста ​

Тест в examples/harness-labs/fixtures/algi-pain-diary/tests/test_domain.py создаёт три заметки: боль после прогулки, улучшение после отдыха, прерванный сон. В конце есть проверки:

python
self.assertNotIn("@", rendered)
self.assertNotIn("+1", rendered)

Во входных заметках нет ни адреса, ни телефона. Такой тест проходит и у функции, которая просто копирует заметки в сводку. Именно это первая реализация и делает.

После второго шага практики, до добавления отчёта через v03, выполните:

bash
PYTHONPATH="$LAB_ROOT/algi" python3 - <<'PY'
from algi import clinician_summary, validate_pain_entry

entry = validate_pain_entry(4, "Напишите на patient@example.com")
summary = clinician_summary([entry])
print(summary["note_snippets"])
assert "patient@example.com" not in repr(summary)
PY

Ожидайте AssertionError и код завершения 1: адрес попал в сводку. Это найденная ошибка учебной реализации. Тесты были зелёными, потому что не использовали данные, способные её обнаружить.

Сначала проверка, которая различает два поведения ​

Для исправления нужен тест, который падает на старом коде и проходит после изменения. В нём должны быть конкретные входные данные и ожидаемый результат. Для адреса выше достаточно проверить отсутствие именно patient@example.com, а также сохранение разрешённой части отчёта.

Затем проверьте уже работавшие сценарии: допустимые баллы, нормализацию пробелов, расчёт среднего. Эти два набора часто называют FAIL_TO_PASS и PASS_TO_PASS: новый тест обнаруживает исправляемую ошибку, старые защищают существующее поведение.

Во втором этапе ALGI тест test_report_redacts_direct_identifiers уже передаёт адрес и телефон во входных данных. Это сильнее первого теста, но всё ещё не доказывает удаление любых идентификаторов. Регулярные выражения не распознают полные имена, а прямое создание PainEntry может обойти обработку в validate_pain_entry.

Есть и отдельный вопрос к месту исправления: второй fixture очищает заметку при вводе. Тест на выходной отчёт не скажет, было ли допустимо менять исходную запись. Для этого нужно решение в спецификации и проверка сохранности данных.

В каком порядке строить набор проверок ​

Сначала возьмите поведение из задачи и случай, на котором оно нарушалось. Затем добавьте границы и существующие сценарии, которые изменение может затронуть. Для дневника это значения 0 и 10, выход за диапазон, неверный тип, пустой список записей и заметка с контактом.

Статические проверки подключайте из уже принятого набора проекта: форматирование, lint, проверку типов, сборку. Они ловят другой класс ошибок. Для маленького Python-стенда py_compile проверяет синтаксис, но запуск тестов всё равно обязателен.

Когда появляются база или API, добавьте интеграционную проверку пути данных. Unit-тест функции отчёта не покажет, что API отдал записи другого пользователя. Для интерфейса потребуется проверка в браузере: успешная сборка не гарантирует, что форму можно заполнить.

Не переносите все проверки проекта в каждую задачу без разбора. Выберите обязательный быстрый набор для каждого запуска и более широкий набор перед объединением изменений. Основание выбора - какие ошибки изменение способно внести.

Что проверять независимо от автора ​

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

Для условий, которые трудно выразить assert, пригодится оценочная шкала. Например, для текста отчёта задайте примеры допустимых формулировок и конкретные причины отклонения. Человек или отдельная модель-оценщик применяет одну и ту же шкалу к результатам.

LLM-оценщик тоже ошибается. Перед использованием сравните его оценки с решениями специалиста на примерах, которых не было при настройке. Сохраняйте версию инструкции и разногласия. Дисклеймер сам по себе не делает произвольный текст корректным или пригодным для медицинского использования; здесь мы проверяем только учебные примеры.

Как runner принимает решение ​

В задаче указана команда:

json
{
  "name": "unit tests",
  "command": ["python3", "-m", "unittest", "discover", "-s", "tests"]
}

v02 записывает check_started, выполняет команду и сохраняет check_finished с кодом завершения и выводом. v03 перед этим проверяет policy. Команда py_compile текущей policy v03 не разрешена, поэтому просто добавить её в задачу недостаточно.

СитуацияТекущее поведение v03Решение при приёмке
Все команды вернули 0doneПроверить, покрыты ли требования и закончено ли необходимое ревью.
Тест завершился ошибкойfailedРазобрать вывод и поставить исправление.
Команда запрещена policyblockedПроверить необходимость команды и права; не обходить отказ повтором.
Файла контекста нетblockedВосстановить контекст или уточнить задачу.
Проверки прошли, но нужен специалистВсё ещё doneВручную направить на ревью; автоматический needs_review ещё предстоит добавить.

Когда повторять запуск ​

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

v01-v03 не повторяют работу автоматически. При добавлении этого механизма различайте повтор проверки над готовыми файлами и повтор применения backend: fixture может затереть ручное исправление. У v03 есть --backend none, позволяющий запустить проверки без повторного применения fixture.

Для завершения упражнения сопоставьте каждый пункт задачи с проверкой или решением ревью. Пустая ячейка покажет, какое требование ещё нельзя считать принятым. Следующая глава поможет найти эти проверки в журнале.

Хендбук по Agentic Engineering